- Text3DCtrl: 新增SetName(text, area, suffix)重载,各部分独立翻译 - CarCtrl.Update3DText: 从carName中分离(1)等后缀,纯名称查翻译表 - 修复车辆展开后名称含中文问题(组合字符串无法匹配翻译表) - 修复收起/展开后文字不刷新问题(LanguageChanged事件重建文本)
425 lines
13 KiB
C#
425 lines
13 KiB
C#
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<CarState> carStateChangedEvent;
|
|
public UnityAction<CarCtrl> carOpenedEvent;//车辆展开完成事件
|
|
public UnityAction<bool> selcetChangedEvent;//车辆选中状态变化事件
|
|
|
|
public CarPosType carType;//车辆类型 首车 或者跟随车
|
|
public CarCtrlType ctrlType = CarCtrlType.AI;
|
|
//List<Vector3> 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<CarAIExtendCtrl>();
|
|
carController = this.transform.GetComponent<CarController>();
|
|
//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<CarSyncHandler>();
|
|
this.gameObject.AddComponent<CarSyncSender>();
|
|
}
|
|
}
|
|
|
|
//注入车载物体
|
|
public void SetOnboardEquip(GameObject onBoardEquipPrefab,string equipName)
|
|
{
|
|
if (onBoardEquipPrefab != null)
|
|
{
|
|
onboardGO = Instantiate<GameObject>(onBoardEquipPrefab);
|
|
onboardGO.GetComponent<OnBoardEquipCtrl>().SetInitName(equipName);//车名+车载物体名组成唯一标识
|
|
onboardAnim = onboardGO.GetComponent<IAnimation>();
|
|
onboardGO.gameObject.SetActive(false);//开始隐藏车载物体
|
|
}
|
|
}
|
|
|
|
//开始使用VR控制 关闭AI控制逻辑
|
|
public void StartVRCtrl()
|
|
{
|
|
if (carAI)
|
|
carAI.enabled = false;
|
|
}
|
|
|
|
//结束VR控制 启用AI控制逻辑
|
|
public void StopVRCtrl()
|
|
{
|
|
if (carAI)
|
|
carAI.enabled = true;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 改变车辆文字颜色 红色代表已经选取状态 绿色代表选可选取 蓝色代表其他人操控中
|
|
/// </summary>
|
|
/// <param name="color"></param>
|
|
private void ChangeTextColor(Color color)
|
|
{
|
|
//if (Text3DCtrl_Names==null)
|
|
// Text3DCtrl_Names = this.GetComponentsInChildren<Text3DCtrl>();
|
|
for (int i = 0; i < Text3DCtrl_Names.Length; i++)
|
|
{
|
|
Text3DCtrl_Names[i]?.ChangeTextColor(color);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 绑定同步UI
|
|
/// </summary>
|
|
/// <param name="iconBase"></param>
|
|
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<GameObjectPiaker>().InjectGO(onboardGO.GetComponent<IPicked>());//展开时 显示车载物体并开始移动位置 展开动画待放置成功后开始播放
|
|
}
|
|
}
|
|
//播放 展开动画 待完成
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 设置路径点
|
|
/// </summary>
|
|
/// <param name="points"></param>
|
|
public void SetWayPoints(List<Vector3> points)
|
|
{
|
|
//wayPoints = points;
|
|
if (CarState == CarState.moving || CarState == CarState.parking) //驻车状态或运动状态可以设置路点移动 否则无法移动
|
|
{
|
|
if (carAI == null)
|
|
carAI = this.transform.GetOrAddComponent<CarAIExtendCtrl>();
|
|
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();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 控制车辆移动
|
|
/// </summary>
|
|
/// <param name="hor">水平方向</param>
|
|
/// <param name="ver">竖直方向</param>
|
|
/// <param name="handBreak">刹车</param>
|
|
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<Text3DCtrl>();
|
|
|
|
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,
|
|
}
|
|
|