本人在项目开发中原创脚本,转载请注明来源,谢谢!!
脚本说明
此脚本的编辑是为了实现3D场景中多个人物模型(物体)按照同一轨迹点进行漫游移动并旋转的功能。
- 所有人物模型在同一轨迹上的不同位置点(开始漫游点位置)
- 所有人物模型朝着同一个目标点漫游,且按照同一轨迹点进行漫游并旋转
具体脚本内容如下所示:
脚本中的有两种获取漫游点坐标的方式,根据个人喜好选择使用。
wayPiontsParent.GetChild(wayIndex).position 直接获取漫游点坐标
wayPointsList[wayIndex].position 将所有漫游点存储在List中然后再去获取对应的漫游点坐标
(脚本可以根据自己的项目内容进一步优化)
(漫游效果可以根据需求进一步优化脚本逻辑)
方法一:在人物(物体)模型上手动添加脚本及修改相应参数
- 3D场景布置漫游的轨迹点
- 场景中在漫游点开始处添加人物(物体)模型
- 脚本挂载到需要漫游的人物(物体)模型上
- 修改挂载脚本中开始漫游点的值和添加所有漫游点的父类,挂载后人物(物体)模型上显示如下图所示:
方法一具体脚本如下所示:
[SerializeField]
private int wayIndex = 0;//人物初始点位置
[SerializeField]
private Transform wayPiontsParent;//所有漫游点的父类
private List<Transform> wayPointsList = new List<Transform>();//存储所有漫游点
private float normal_moveSpeed = 3f;//移动速度
private float normal_rotateSpeed = 2f;//旋转速度
float rotateProgress = 0;
Quaternion targetQuaternion;//目标
Quaternion lastQuaternion;//人物
void Start()
{
InitWayPoints();
CaculateRotateData(wayIndex);
transform.position = wayPiontsParent.GetChild(wayIndex).position/* wayPointsList[wayIndex].position*/;
}
/// <summary>
/// 初始化轨迹点
/// </summary>
void InitWayPoints()
{
wayPointsList.Clear();
if (wayPiontsParent != null && wayPiontsParent.childCount > 0)
{
for (int i = 0; i < wayPiontsParent.childCount; i++)
{
wayPointsList.Add(wayPiontsParent.GetChild(i));
}
}
}
void Update()
{
NormalMove();
}
/// <summary>
/// 正常漫游
/// </summary>
private void NormalMove()
{
if (peopleMoveStatus == PeopleMoveStatus.Move)
{
float nextPointDistance = 0;
if (wayIndex < wayPiontsParent.childCount - 1/* wayPointsList.Count - 1*/)//没有到最后一个点
{
nextPointDistance = Vector3.Distance(transform.position, wayPiontsParent.GetChild(wayIndex + 1).position);
Vector3 direction = (wayPiontsParent.GetChild(wayIndex + 1).position - wayPiontsParent.GetChild(wayIndex).position).normalized;
transform.position += Time.deltaTime * direction * normal_moveSpeed;
//nextPointDistance = Vector3.Distance(transform.position, wayPointsList[wayIndex + 1].position);
//Vector3 direction = (wayPointsList[wayIndex + 1].position - wayPointsList[wayIndex].position).normalized;
//transform.position += Time.deltaTime * direction * normal_moveSpeed;
}
if (wayIndex.Equals(wayPiontsParent.childCount - 1/*wayPointsList.Count - 1*/))//最后一个点
{
Destroy(this.gameObject);
}
if (nextPointDistance <= 0.15f)//换到下一个点进行旋转
{
peopleMoveStatus = PeopleMoveStatus.Rotate;
rotateProgress = 0;
wayIndex++;
CaculateRotateData(wayIndex);
}
}
if (peopleMoveStatus == PeopleMoveStatus.Rotate && lastQuaternion != targetQuaternion)
{
transform.rotation = Quaternion.Lerp(lastQuaternion, targetQuaternion, rotateProgress);
rotateProgress += Time.deltaTime * normal_rotateSpeed;
if (lastQuaternion == targetQuaternion || rotateProgress >= 1)
{
peopleMoveStatus = PeopleMoveStatus.Move;//转完了,开始移动
}
}
}
/// <summary>
/// 计算旋转方向数据
/// </summary>
/// <param name="index"></param>
void CaculateRotateData(int index)
{
lastQuaternion = transform.rotation;
Vector3 dir = Vector3.zero;
if (wayIndex < wayPiontsParent.childCount - 1 /*wayPointsList.Count - 1*/)
{
dir = wayPiontsParent.GetChild(index + 1).position - wayPiontsParent.GetChild(index).position;
//dir = wayPointsList[index + 1].position - wayPointsList[index].position;
}
targetQuaternion = Quaternion.LookRotation(dir);
}
PeopleMoveStatus peopleMoveStatus = PeopleMoveStatus.Move;
/// <summary>
/// 人物模型移动状态
/// </summary>
enum PeopleMoveStatus
{
Move,
Rotate,
End
}
方法二:在人物(物体)上动态添加脚本及修改相应参数
初始化轨迹点的方法添加到控制动态生成人物模型的脚本中,脚本如下所示:
/// <summary>
/// 初始化轨迹点
/// </summary>
void InitWayPoints()
{
wayPointsList.Clear();
if (wayRoot != null && wayRoot.childCount > 0)
{
for (int i = 0; i < wayRoot.childCount; i++)
{
wayPointsList.Add(wayRoot.GetChild(i).position);
}
}
}
控制动态生成人物模型的脚本中添加如下脚本:
/// <summary>
/// 初始化多个人物模型
/// </summary>
private void InitSomePeople()
{
for (int i = 0; i < 30; i += 2)
{
GameObject peopleWalk = Instantiate(peoplePrefab, peopleParent.position, peopleParent.rotation);
peopleWalk.transform.SetParent(peopleParent);
peopleWalk.AddComponent<SomePeopleWalkControl>().SetWayIndex(i);
}
}
控制人物模型按照轨迹点移动的脚本如下所示:
private int wayIndex = 0;//人物初始点位置
private float normal_moveSpeed = 0.5f;//移动速度
private float normal_rotateSpeed = 5f;//旋转速度
float rotateProgress = 0;
Quaternion targetQuaternion;//目标
Quaternion lastQuaternion;//人物
void Start()
{
transform.position = BornPeople.Instance.wayPointsList[wayIndex];
CaculateRotateData(wayIndex);
transform.rotation = Quaternion.LookRotation(initDir);//初始化物体朝向下一漫游点方向
}
/// <summary>
/// 给人物模型初始漫游点赋值
/// </summary>
public void SetWayIndex(int _index)
{
wayIndex = _index;
}
void Update()
{
NormalMove();
}
/// <summary>
/// 正常漫游
/// </summary>
private void NormalMove()
{
if (peopleMoveStatus == PeopleMoveStatus.Move)
{
float nextPointDistance = 0;
if (wayIndex < BornPeople.Instance.wayPointsList.Count - 1)//没有到最后一个点
{
//nextPointDistance = Vector3.Distance(transform.position, wayPiontsParent.GetChild(wayIndex + 1).position);
//Vector3 direction = (wayPiontsParent.GetChild(wayIndex + 1).position - wayPiontsParent.GetChild(wayIndex).position).normalized;
//transform.position += Time.deltaTime * direction * normal_moveSpeed;
nextPointDistance = Vector3.Distance(transform.position, BornPeople.Instance.wayPointsList[wayIndex + 1]);
Vector3 direction = (BornPeople.Instance.wayPointsList[wayIndex + 1] - BornPeople.Instance.wayPointsList[wayIndex]).normalized;
transform.position += Time.deltaTime * direction * normal_moveSpeed;
}
if (wayIndex.Equals(BornPeople_14.Instance.wayPointsList.Count - 1/*wayPointsList.Count - 1*/))//最后一个点
{
Destroy(this.gameObject);
}
if (nextPointDistance <= 0.15f)//换到下一个点进行旋转
{
peopleMoveStatus = PeopleMoveStatus.Rotate;
rotateProgress = 0;
wayIndex++;
CaculateRotateData(wayIndex);
}
}
if (peopleMoveStatus == PeopleMoveStatus.Rotate && lastQuaternion != targetQuaternion)
{
transform.rotation = Quaternion.Lerp(lastQuaternion, targetQuaternion, rotateProgress);
rotateProgress += Time.deltaTime * normal_rotateSpeed;
if (lastQuaternion == targetQuaternion || rotateProgress >= 1)
{
peopleMoveStatus = PeopleMoveStatus.Move;//转完了,开始移动
}
}
}
Vector3 initDir = Vector3.zero;
/// <summary>
/// 计算旋转方向数据
/// </summary>
/// <param name="index"></param>
public void CaculateRotateData(int index)
{
lastQuaternion = transform.rotation;
Vector3 dir = Vector3.zero;
if (index < BornPeople.Instance.wayPointsList.Count - 1 /*wayPointsList.Count - 1*/)
{
//dir = wayPiontsParent.GetChild(index + 1).position - wayPiontsParent.GetChild(index).position;
dir = BornPeople.Instance.wayPointsList[index + 1] - BornPeople.Instance.wayPointsList[index];
}
initDir = dir;
targetQuaternion = Quaternion.LookRotation(dir);
}
PeopleMoveStatus peopleMoveStatus = PeopleMoveStatus.Move;
/// <summary>
/// 人物模型移动状态
/// </summary>
enum PeopleMoveStatus
{
Move,
Rotate,
End
}