unityzgy/Assets/Scripts/GameObjectCtrl/CarCtrl.cs
ayuan9957 6909b1c7b4 fix: 3D文字翻译重构 - 分离车辆名称/厂区名称/后缀独立翻译
- Text3DCtrl: 新增SetName(text, area, suffix)重载,各部分独立翻译
- CarCtrl.Update3DText: 从carName中分离(1)等后缀,纯名称查翻译表
- 修复车辆展开后名称含中文问题(组合字符串无法匹配翻译表)
- 修复收起/展开后文字不刷新问题(LanguageChanged事件重建文本)
2026-07-16 16:25:50 +08:00

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,
}