unity--城市道路车辆行驶

目录

1.示意图

 1.1行驶路线与红绿灯

2. 层级面板

2.1红绿灯

 2.2车辆路径点

 3.属性面板

3.1红绿灯

3.2路径点

4.脚本代码

4.1 控制脚本

4.2红绿灯脚本

4.3路径点脚本

4.4车辆控制脚本

5.实现效果


1.示意图

 1.1行驶路线与红绿灯

2. 层级面板

2.1红绿灯

 2.2车辆路径点

除了四个角-其余路口均有4个路径点

 3.属性面板

3.1红绿灯

3.2路径点

 

4.脚本代码

4.1 控制脚本

using UnityEngine;

public class RoadContr : MonoBehaviour
{
    public TrafficLight[] trafficLights; // 红绿灯数组
    public WayPoint[] wayPoints; //路径
    public Transform pare;
    [SerializeField]
    private Map_Car[] fabCar;

    private int carNum = 0;

    private void OnEnable()
    {
        InvokeRepeating("CarCreate", 1, 1);
    }

    private void CarCreate()
    {
        if (carNum < 50)
        {
            carNum++;
            Map_Car car = Instantiate(fabCar[Random.Range(0, 10)], pare);
            WayPoint way = wayPoints[Random.Range(0, wayPoints.Length)];
            car.transform.position = way.transform.position;
            car.Init(way);
        }
        else
        {
            CancelInvoke("CarCreate");
        }
    }
}

4.2红绿灯脚本

using UnityEngine;

public class TrafficLight : MonoBehaviour
{
    private bool isBegin = false;

    private float redTime;
    public bool isRed = false;

    private void OnEnable()
    {
        redTime = Random.Range(3, 15);
        isBegin = true;
    }

    private void Update()
    {
        if (!isBegin)
        {
            return;
        }
        redTime -= Time.deltaTime;
        if (redTime <= 0)
        {
            isRed = !isRed;
            redTime = Random.Range(3, 15);
        }
    }
}

4.3路径点脚本

using System.Collections.Generic;
using UnityEngine;

public class WayPoint : MonoBehaviour
{
    [Header("0上1下2左3右")]
    [SerializeField]
    private List<int> Direction = new();

    [Header("下一路径点")]
    public List<WayPoint> nextWayPoints_1;
    public List<WayPoint> nextWayPoints_2;
    [Header("当前路径点所属红绿灯")]
    public TrafficLight trafficLight;

    /// <summary>
    /// 0上1下2左3右
    /// </summary>
    [HideInInspector]
    public int directionSelect = -1;


    private int randomNum = -1;
    /// <summary>
    /// 获取下一路径点
    /// </summary>
    /// <returns></returns>
    public WayPoint GetNextWayPoint()
    {
        if (Direction.Count == 1)
        {
            directionSelect = Direction[0];
            if (nextWayPoints_1.Count == 1)
            {
                return nextWayPoints_1[0];
            }
            else
            {
                return nextWayPoints_1[Random.value < 0.5 ? 0 : 1];
            }
        }
        else
        {
            randomNum = Random.value < 0.5 ? 0 : 1;
            directionSelect = Direction[randomNum];
            if (randomNum == 0)
            {
                if (nextWayPoints_1.Count == 1)
                {
                    return nextWayPoints_1[0];
                }
                else
                {
                    return nextWayPoints_1[Random.value < 0.5 ? 0 : 1];
                }
            }
            else
            {
                if (nextWayPoints_2.Count == 1)
                {
                    return nextWayPoints_2[0];
                }
                else
                {
                    return nextWayPoints_2[Random.value < 0.5 ? 0 : 1];
                }
            }
        }
    }

}

4.4车辆控制脚本

using UnityEngine;

public class Map_Car : MonoBehaviour
{
    private WayPoint curWay;       // 当前路径点
    private WayPoint nextWay;       // 下一路径点
    private TrafficLight trafficLight;
    public float moveSpeed = 3f;        // 车辆移动速度
    public float minDistance = 2f;      // 最小车距

    private bool canMove = true;

    private bool isBegin = false;

    private Vector3 nextWaypointPos;
    private Quaternion currentWaypointRot;
    private Vector3 targetDirection;

    [SerializeField]
    private int direction = -1;

    public void Init(WayPoint cur_way)
    {
        curWay = cur_way;
        nextWay = curWay.GetNextWayPoint();
        trafficLight = curWay.trafficLight;

        nextWaypointPos = nextWay.transform.position;
        direction = curWay.directionSelect;
        switch (direction)
        {
            case 0:
                currentWaypointRot = Quaternion.Euler(0, 180, 0);
                break;
            case 1:
                currentWaypointRot = Quaternion.Euler(0, 0, 0);
                break;
            case 2:
                currentWaypointRot = Quaternion.Euler(0, 90, 0);
                break;
            case 3:
                currentWaypointRot = Quaternion.Euler(0, 270, 0);
                break;
        }
        // 计算车辆朝向下一个路径点的方向
        targetDirection = nextWaypointPos - transform.position;
        targetDirection.y = 0f; // 将方向的y轴分量设为0,使车辆在平面上移动
        targetDirection.Normalize(); // 归一化方向向量

        isBegin = true;
    }

    private void Update()
    {
        if (!isBegin) { return; }

        // 如果车辆离当前路径点很近,则停下来等待红灯
        if (Vector3.Distance(transform.position, nextWaypointPos) <= 2.5f)
        {
            // 获取当前路口的红绿灯状态
            if (trafficLight.isRed)
            {
                switch (direction)
                {
                    case 0:
                    case 1:
                        canMove = false;
                        break;
                    case 2:
                    case 3:
                        canMove = true;
                        break;
                }
            }
            else
            {
                switch (direction)
                {
                    case 0:
                    case 1:
                        canMove = true;
                        break;
                    case 2:
                    case 3:
                        canMove = false;
                        break;
                }
            }
            if (Vector3.Distance(transform.position, nextWaypointPos) <= 0.1f)
            {
                Init(nextWay);
            }
        }

        if (canMove)
        {
            // 否则,根据车辆移动速度向前移动
            transform.Translate(targetDirection * moveSpeed * Time.deltaTime, Space.World);
            transform.rotation = Quaternion.Lerp(transform.rotation, currentWaypointRot, 0.1f); // 平滑旋转到目标方向

            // 检查前方是否有其他车辆,并保持车距
            RaycastHit hit;
            if (Physics.Raycast(transform.position, -transform.forward, out hit, minDistance))
            {
                moveSpeed = 0f;
                //Debug.DrawRay(transform.position, -transform.forward * minDistance, Color.red);
            }
            else
            {
                // 否则,继续移动
                moveSpeed = 3f; // 恢复车辆移动速度
                //Debug.DrawRay(transform.position, -transform.forward * minDistance, Color.green);
            }
        }
    }
}

5.实现效果

城市道路

猜你喜欢

转载自blog.csdn.net/lalate/article/details/131209249