unity建造物体

接上一回unity做一个简单的运输带

物体可以在运输带上移动了,但是运输带还得一个一个安放,效率比较低下,下面实现一下建造传输带的功能

建造部分参考了这篇文章

用Unity盖房子(一):《勇者斗恶龙:建造者2》游戏功能的猜想

首先我们的传输带是1m的立方体,它的中心在0.5的位置,所以如果要在平面上进行建造,需要从鼠标发射一条射线,而射线碰撞点的坐标转换为0.5的倍数

public static Vector3 FromWorldPositionToCubePosition (Vector3 position) {
    
    
    Vector3 resut = Vector3.zero;
    resut.x = position.x > 0 ? (int) position.x * 1f + 0.5f : (int) position.x * 1f - 0.5f;
    resut.y = position.y > 0 ? (int) position.y * 1f + 0.5f : (int) position.y * 1f - 0.5f;
    resut.z = position.z > 0 ? (int) position.z * 1f + 0.5f : (int) position.z * 1f - 0.5f;
    return resut;
}

然后就是发射射线并生成传输带了

先生成一个cube用来显示安放位置,点击左键再实例化传输带

void Update () {
    
    
    if (GetMouseRayPoint (out addCubePos)) {
    
    
        cube.transform.position = addCubePos;
        if (Input.GetMouseButtonDown (0)) {
    
    
            Instantiate (wheelPb, addCubePos, wheelPb.transform.rotation);
        }
    }
}
bool GetMouseRayPoint (out Vector3 pos) {
    
    
    Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
    RaycastHit hitInfo;
    if (Physics.Raycast (ray, out hitInfo)) {
    
    
        pos = FromWorldPositionToCubePosition (hitInfo.point - ray.direction * 0.001f);
        return true;
    }
    pos = Vector3.zero;
    return false;
}

完整代码

using System.Collections;
using System.Collections.Generic;

using UnityEngine;

public class Builder : MonoBehaviour {
    
    
    // Start is called before the first frame update
    private Vector3 addCubePos;
    public GameObject cube;
    public GameObject wheelPb;
    void Start () {
    
    

    }
    void Update () {
    
    
        if (GetMouseRayPoint (out addCubePos)) {
    
    
            cube.transform.position = addCubePos;
            if (Input.GetMouseButtonDown (0)) {
    
    
                Instantiate (wheelPb, addCubePos, wheelPb.transform.rotation);
            }
        }
    }
    bool GetMouseRayPoint (out Vector3 pos) {
    
    
        Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
        RaycastHit hitInfo;
        if (Physics.Raycast (ray, out hitInfo)) {
    
    
            pos = FromWorldPositionToCubePosition (hitInfo.point - ray.direction * 0.001f);
            return true;
        }
        pos = Vector3.zero;
        return false;
    }
    public static Vector3 FromWorldPositionToCubePosition (Vector3 position) {
    
    
        Vector3 resut = Vector3.zero;
        resut.x = position.x > 0 ? (int) position.x * 1f + 0.5f : (int) position.x * 1f - 0.5f;
        resut.y = position.y > 0 ? (int) position.y * 1f + 0.5f : (int) position.y * 1f - 0.5f;
        resut.z = position.z > 0 ? (int) position.z * 1f + 0.5f : (int) position.z * 1f - 0.5f;
        return resut;
    }
}

建造效果

但是这样还是只能一个一个点击来建造,所以再写一个根据点击两点生成直线传输带的效果

暂时只考虑同一水平高度的情况下

void Update () {
    
    
    if (GetMouseRayPoint (out addCubePos)) {
    
    
        cube.transform.position = addCubePos;
        if (Input.GetMouseButtonDown (0)) {
    
    
            if (lastCubePos != Vector3.zero) {
    
    
                List<Vector3> addCubesPos = GetAddCubesPos (lastCubePos, addCubePos);
                foreach (var pos in addCubesPos) {
    
    
                    Instantiate (wheelPb, pos, wheelPb.transform.rotation);
                }
            }
            else {
    
    
                Instantiate (wheelPb, addCubePos, wheelPb.transform.rotation);
            }
            lastCubePos = addCubePos;
        }
    }
}
List<Vector3> GetAddCubesPos (Vector3 startPos, Vector3 endPos) {
    
    
    List<Vector3> cubesPos = new List<Vector3>();
    int xLength = (int) (endPos.x - startPos.x);
    int zLength = (int) (endPos.z - startPos.z);
    Vector3 currentPos;
    if (xLength != 0) {
    
    
        int xDir = xLength / Mathf.Abs (xLength);
        currentPos = startPos;
        for (int i = 0; i != xLength; i += xDir) {
    
    
            currentPos += Vector3.right * xDir;
            cubesPos.Add (currentPos);
        }
        startPos = currentPos;
    }
    if (zLength != 0) {
    
    
        int zDir = zLength / Mathf.Abs (zLength);
        currentPos = startPos;
        for (int i = 0; i != zLength; i += zDir) {
    
    
            currentPos += Vector3.forward * zDir;
            cubesPos.Add (currentPos);
        }
    }
    return cubesPos;
}

直线建造效果

增加预览效果

void Update () {
    
    
    if (GetMouseRayPoint (out addCubePos)) {
    
    
        cube.transform.position = addCubePos;
        List<Vector3> addCubesPos = new List<Vector3> ();
        if (lastCubePos != Vector3.zero) {
    
    
            addCubesPos = GetAddCubesPos (lastCubePos, addCubePos);
        }
        if (Input.GetMouseButtonDown (0)) {
    
    
            if (lastCubePos != Vector3.zero) {
    
    
                foreach (var pos in addCubesPos) {
    
    
                    Instantiate (wheelPb, pos, wheelPb.transform.rotation);
                }
            }
            else {
    
    
                Instantiate (wheelPb, addCubePos, wheelPb.transform.rotation);
            }
            lastCubePos = addCubePos;
        }
    }
}
List<Vector3> GetAddCubesPos (Vector3 startPos, Vector3 endPos) {
    
    
    foreach (var item in cubes) {
    
    
        Destroy (item);
    }
    cubes.Clear ();
    List<Vector3> cubesPos = new List<Vector3> ();
    int xLength = (int) (endPos.x - startPos.x);
    int zLength = (int) (endPos.z - startPos.z);
    Vector3 currentPos;
    if (xLength != 0) {
    
    
        int xDir = xLength / Mathf.Abs (xLength);
        currentPos = startPos;
        for (int i = 0; i != xLength; i += xDir) {
    
    
            currentPos += Vector3.right * xDir;
            cubesPos.Add (currentPos);
        }
        startPos = currentPos;
    }
    if (zLength != 0) {
    
    
        int zDir = zLength / Mathf.Abs (zLength);
        currentPos = startPos;
        for (int i = 0; i != zLength; i += zDir) {
    
    
            currentPos += Vector3.forward * zDir;
            cubesPos.Add (currentPos);
        }
    }
    foreach (var pos in cubesPos) {
    
    
        cubes.Add (Instantiate (cube, pos, cube.transform.rotation));
    }
    return cubesPos;
}

再给生成的运输带绑定移动路径

void Update () {
    
    
        if (GetMouseRayPoint (out addCubePos)) {
    
    
            cube.transform.position = addCubePos;
            List<Vector3> addCubesPos = new List<Vector3> ();
            if (lastCubePos != Vector3.zero) {
    
    
                addCubesPos = GetAddCubesPos (lastCubePos, addCubePos);
            }
            if (Input.GetMouseButtonDown (0)) {
    
    
                if (lastCubePos != Vector3.zero) {
    
    
                    //如果是连接两点 记录各个传输点
                    List<GameObject> wheels = new List<GameObject> ();
                    wheels.Add (lastNode);
                    foreach (var pos in addCubesPos) {
    
    
                        wheels.Add (Instantiate (wheelPb, pos, wheelPb.transform.rotation));
                    }
                    //将两点直接路径绑定
                    for (int i = 0; i < wheels.Count - 1; i++) {
    
    
                        wheels[i].GetComponent<Wheel> ().paths.Add (wheels[i].transform);
                        wheels[i].GetComponent<Wheel> ().paths.Add (wheels[i + 1].transform);
                    }

                    lastNode = wheels[wheels.Count - 1];
                }
                else {
    
    
                    //记录最后一个/上一个安放的点
                    lastNode = Instantiate (wheelPb, addCubePos, wheelPb.transform.rotation);
                }
                lastCubePos = addCubePos;
            }
        }
    }

运输物体的效果

但是这样区分度不够高,所以我找到了这篇文章,将预览的方块变成线框

unity显示物体线框,外边框

使用后的效果

猜你喜欢

转载自blog.csdn.net/qq_25969985/article/details/113409903
今日推荐