using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; using XFramework; using UnityStandardAssets.Vehicles.Car; using System; using UnityEngine.Events; public class CarCtrl : MonoBehaviour, IBindIcon,IShowName3DText { CarData data; CarAIExtendCtrl carAI; CarController carController; Transform targetTransform;//跟随目标 GameObject onboardGO;//车载物体 IAnimation onboardAnim = null;//车载物体动画控制接口 Text3DCtrl [] Text3DCtrl_Names = new Text3DCtrl[2];//车辆名称显示文字 两个名字 分别用于VR和主相机 public UnityAction carStateChangedEvent; public UnityAction carOpenedEvent;//车辆展开完成事件 public UnityAction selcetChangedEvent;//车辆选中状态变化事件 public CarPosType carType;//车辆类型 首车 或者跟随车 public CarCtrlType ctrlType = CarCtrlType.AI; //List wayPoints;//路点 首车使用 public IconBase iconBase_thisIcon; bool openAnimation = false;//是否为展开命令 private CarState carState = CarState.parking; bool isSelect = false;//是否处于选中状态 默认未选中 public bool IsSelect { set { if (isSelect != value) { isSelect = value; selcetChangedEvent?.Invoke(isSelect); ChangeTextColor(isSelect ? Color.red : Color.green);//选中红色 未选中绿色 他人选中蓝色 } } get { return isSelect; } } string inAreaName;//所属分区名称 bool otherUserCtrl = false;//是否他人正在控制 public bool OtherUserCtrl { set { otherUserCtrl = value; ChangeTextColor(otherUserCtrl ? Color.blue : Color.green); } get { return otherUserCtrl; } } public CarState CarState { set { carState = value; carStateChangedEvent?.Invoke(carState); if (carState == CarState.opened) carOpenedEvent?.Invoke(this); if (carState == CarState.moving)//车辆转为移动状态时 清空当前分区状态 SetArea(""); } get { return carState; } }//默认处于驻车状态 // Start is called before the first frame update void Awake() { carAI = this.transform.GetOrAddComponent(); carController = this.transform.GetComponent(); //CarGameObjectManager.Instance.SetNewCar(this); //CarGameObjectManager.Instance.StartPersonCtrl(); } //初始化车辆信息 public void SetInitData(CarData carData) { data = carData; if (carData.icon) BindIcon(carData.icon); this.transform.position = carData.postion; this.transform.name = carData.carName; this.transform.eulerAngles = carData.rotation; carType = carData.carType; carController.MaxSpeed = carData.Speed; //navMeshAgent.radius = 2; //navMeshAgent.height = 3; if (carType == CarPosType.fllowCar)//跟随车保持距离 carAI.fllowKeepDis = carData.stopDistance; if (GroupLearnHelper.isGroup)//添加车辆同步组件 { this.gameObject.AddComponent(); this.gameObject.AddComponent(); } } //注入车载物体 public void SetOnboardEquip(GameObject onBoardEquipPrefab,string equipName) { if (onBoardEquipPrefab != null) { onboardGO = Instantiate(onBoardEquipPrefab); onboardGO.GetComponent().SetInitName(equipName);//车名+车载物体名组成唯一标识 onboardAnim = onboardGO.GetComponent(); onboardGO.gameObject.SetActive(false);//开始隐藏车载物体 } } //开始使用VR控制 关闭AI控制逻辑 public void StartVRCtrl() { if (carAI) carAI.enabled = false; } //结束VR控制 启用AI控制逻辑 public void StopVRCtrl() { if (carAI) carAI.enabled = true; } /// /// 改变车辆文字颜色 红色代表已经选取状态 绿色代表选可选取 蓝色代表其他人操控中 /// /// private void ChangeTextColor(Color color) { //if (Text3DCtrl_Names==null) // Text3DCtrl_Names = this.GetComponentsInChildren(); for (int i = 0; i < Text3DCtrl_Names.Length; i++) { Text3DCtrl_Names[i]?.ChangeTextColor(color); } } /// /// 绑定同步UI /// /// public void BindIcon(IconBase icon) { iconBase_thisIcon = icon; icon.SetName(data.carName); } //展开/收车 internal void ChangeOpening(bool isVR=false) { if (isVR && onboardGO != null && !openAnimation)//VR模式下 存在车载物体时只能收起不能展开 return; if (CarState == CarState.openingAnim || CarState == CarState.closingAnim || CarState == CarState.moving) return;//动画过程中不执行新的指令 车辆运动状态无法展开 openAnimation = !openAnimation; onboardAnim?.AddPlayOverEvent(ChildAnimPlayOver); childAnimPlayOver = false;//开始播放动画时 重置记录的状态 thisAnimPlayOver = false;//重置记录的状态 if (openAnimation)//展开动画 { CarState = CarState.openingAnim; if (onboardGO != null) { if (!otherUserCtrl)//只有自身控制的车辆展开子物体时 创建子物体 其它人员控制的车辆创建的子物体不直接显示车载物体 等待放置成功时 { onboardGO.gameObject.SetActive(true);// CameraCtrl.Instance.transform.GetOrAddComponent().InjectGO(onboardGO.GetComponent());//展开时 显示车载物体并开始移动位置 展开动画待放置成功后开始播放 } } //播放 展开动画 待完成 } else//收起动画 { CarState = CarState.closingAnim; onboardAnim?.Play(-1);//收起命令时 直接发送给子物体 //播放 收起动画 } Invoke("CarAnimationOver", 3f); //注册结束事件 关闭动画状态 转为parking /opened } //将车辆和车载物体展开/收起看成一个动作 即要展开都展开 要收起都收起 展开/收起时必须等待两者均完成放可认为展开结束 bool childAnimPlayOver;//车载物体动画播放完成 bool thisAnimPlayOver;//本车动画播放完成 //子物体车辆动画播放完成 private void ChildAnimPlayOver() { if (CarState == CarState.closingAnim)//收起过程中车载物体动画播放完毕时 隐藏车载物体 { onboardGO.gameObject.SetActive(false); } if (!thisAnimPlayOver)//车辆动画未播放完 只做记录 { childAnimPlayOver = true; } else//车辆动画已经播放完 展开/收起完成 { AnimationOverStateChange(); } } //本车动画播放完毕 private void CarAnimationOver() { if (onboardGO == null)//如果没有子物体 展开/收起动作完成 { AnimationOverStateChange(); } else//记录播放完成状态 未完全完成展开逻辑 { if (!childAnimPlayOver)//子物体动画未播放完成 { thisAnimPlayOver = true;//记录车辆展开完成 } else { AnimationOverStateChange(); } } } //动画完成改变车辆状态 private void AnimationOverStateChange() { switch (CarState) { case CarState.openingAnim: CarState = CarState.opened; break; case CarState.closingAnim: CarState = CarState.parking; break; default: break; } } /// /// 设置路径点 /// /// public void SetWayPoints(List points) { //wayPoints = points; if (CarState == CarState.moving || CarState == CarState.parking) //驻车状态或运动状态可以设置路点移动 否则无法移动 { if (carAI == null) carAI = this.transform.GetOrAddComponent(); if (carAI.enabled)//启用AI控制时设置路点 carAI.SetWayPoint(points.ToArray()); } } //首车之外的车辆跟随前车移动 public void SetFollowTarget(Transform target) { carAI?.SetFllowTarget(target); } //改变车辆的控制方式 public void ChangeCtrlType(CarCtrlType carCtrlType) { ctrlType = carCtrlType; switch (carCtrlType) { case CarCtrlType.AI: carAI.ChangeCtrlType(MoveType.fllow); break; case CarCtrlType.Person: carAI.ChangeCtrlType(MoveType.wayPoints); break; default: break; } } //开始编队自动移动 public void StartMove() { carAI.StartAIMove(); } //停止编队自动移动 public void StopMove() { carAI.StopAIMove(); } /// /// 控制车辆移动 /// /// 水平方向 /// 竖直方向 /// 刹车 public void CarMove(float hor, float ver, float handBreak) { if (CarState == CarState.moving || CarState == CarState.parking) //驻车状态或运动状态可以控制移动 否则无法移动 { carController.Move(hor, ver, ver, handBreak); } } //设置所属分区 public void SetArea(string areaName) { inAreaName = areaName; iconBase_thisIcon?.SetUpdateIconMsg(areaName, "UnderArea"); Update3DText(); } //Text3DCtrl text3D; //更新车辆名称 private void Update3DText() { //if (Text3DCtrl_Names == null) // Text3DCtrl_Names = this.GetComponentsInChildren(); string carName = data.carName; string nameSuffix = ""; int idx = carName.IndexOf('('); if (idx > 0) { nameSuffix = carName.Substring(idx); carName = carName.Substring(0, idx); } string areaName = inAreaName; for (int i = 0; i < Text3DCtrl_Names.Length; i++) { Text3DCtrl_Names[i]?.SetName(carName, areaName, nameSuffix); } } float timer; //运动状态下每5秒更新一次目标点位置 private void Update() { timer += Time.unscaledDeltaTime; if (timer < 0.5f) return;//寻路逻辑,UI同步逻辑0.5F执行一次即可 timer = 0; Vector3 pos = this.transform.position; Vector4 posAndAngle = new Vector4(pos.x, pos.y, pos.z, this.transform.eulerAngles.y); iconBase_thisIcon?.SetUpdateIconMsg(posAndAngle, "UpdatePos");//更新UI位置 if (carController.CurrentSpeed < 0.1f && CarState == CarState.moving) { CarState = CarState.parking; } if (carController.CurrentSpeed > 0.1f && CarState != CarState.moving)//移动状态 自动清空分配的区域 必须驻车展开后再次分配 { CarState = CarState.moving; } } public void Bind3DText(Text3DCtrl text3DCtrl) { if (Text3DCtrl_Names[0] == null)//先创建普通相机的Text Text3DCtrl_Names[0] = text3DCtrl; else //后创建VR相机Text { Text3DCtrl_Names[1] = text3DCtrl; } Update3DText(); ChangeTextColor(isSelect ? Color.red : Color.green);//选中红色 未选中绿色 } public Transform GetTrans() { return this.transform; } } public enum CarPosType { //首车 firstCar, //跟随车 fllowCar, } public enum CarCtrlType { //纯AI模式 AI, //交互控制模式 Person, } public enum CarState { //用与未选择车辆时状态该更新 none, //移动状态 moving, //驻车状态 parking, //展开动画状态 openingAnim, //收起动画状态 closingAnim, //展开完毕 opened, }