using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PetFlow : MonoBehaviour {
public Transform player;
public float maxDis = 5;
private SmoothFollowerObj posFollow; // 控制位置平滑移動
private SmoothFollowerObj lookFollow; // 控制朝向平滑轉換
public Vector3 posistionVector; // 角色位置移動,方向向量
public Vector3 lookVector; //角色朝向變化,朝向向量
private Vector3 lastVelocityDir; // 上一次移動方向
private Vector3 lastPost; // 之前移動目標位置
void Start()
{
posFollow = new SmoothFollowerObj(0.5f, 0.5f);
lookFollow = new SmoothFollowerObj(0.1f, 0.1f);
posFollow.Update(transform.position, 0, true); // 初始位置
lookFollow.Update(player.transform.position, 0, true);
posistionVector = new Vector3(0, 0.5f, 1.7f);
lookVector = new Vector3(0, 0, 1.5f);
lastVelocityDir = player.transform.forward;
lastPost = player.transform.position;
}
void Update()
{
float dis = Vector3.Distance(transform.position, player.position);
if (dis > maxDis)
PetMoveFlow();
}
// 物件移動
void PetMoveFlow()
{
lastVelocityDir += (player.position - lastPost) * 5;
lastPost = player.position;
lastVelocityDir += player.transform.forward * Time.deltaTime;
lastVelocityDir = lastVelocityDir.normalized;
Vector3 horizontal = transform.position - player.position;
Vector3 horizontal2 = horizontal;
Vector3 vertical = player.up;
Vector3.OrthoNormalize(ref vertical, ref horizontal); // https://docs.unity3d.com/ScriptReference/Vector3.OrthoNormalize.html api
// https://docs.unity3d.com/ScriptReference/Vector3-sqrMagnitude.html api
if (horizontal.sqrMagnitude > horizontal2.sqrMagnitude)
horizontal = horizontal2;
transform.position = posFollow.Update(player.position + horizontal * Mathf.Abs(posistionVector.z)
+ vertical * posistionVector.y, Time.deltaTime);
horizontal = lastVelocityDir;
Vector3 look = lookFollow.Update(player.position + horizontal * lookVector.z
- vertical * lookVector.y, Time.deltaTime);
// https://docs.unity3d.com/ScriptReference/Quaternion.FromToRotation.html api
transform.rotation = Quaternion.FromToRotation(transform.forward, look - transform.position) * transform.rotation;
}
}
class SmoothFollowerObj
{
private Vector3 targetPosistion; // 目標位置
private Vector3 position; // 位置
private Vector3 velocity; // 速率
private float smoothingTime; // 平滑時間
private float prediction; // 預測
public SmoothFollowerObj(float smoothingTime)
{
targetPosistion = Vector3.zero;
position = Vector3.zero;
this.smoothingTime = smoothingTime;
prediction = 1;
}
public SmoothFollowerObj(float smoothingTime, float prediction)
{
targetPosistion = Vector3.zero;
position = Vector3.zero;
this.smoothingTime = smoothingTime;
this.velocity = velocity;
}
// 更新位置資訊
public Vector3 Update(Vector3 targetPosistionNew, float dataTime)
{
Vector3 targetvelocity = (targetPosistionNew - targetPosistion) / dataTime; // 獲取目標移動的方向向量
targetPosistion = targetPosistionNew;
float d = Mathf.Min(1, dataTime / smoothingTime);
velocity = velocity * (1 - d) + (targetPosistion + targetvelocity * prediction - position) * d;
position += velocity * Time.deltaTime;
return position;
}
// 根據傳輸進來數據, 重置本地參數
public Vector3 Update(Vector3 targetPosistionNew, float dataTime, bool rest)
{
if (rest)
{
targetPosistion = targetPosistionNew;
position = targetPosistionNew;
velocity = Vector3.zero;
return position;
}
return Update(targetPosistionNew, dataTime);
}
public Vector3 GetPosistion() { return position; }
public Vector3 GetVelocity() { return velocity; }
}
物件跟隨路徑:
程式碼來源: https://blog.csdn.net/BIGMAD/article/details/71698310
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EditorPathScript : MonoBehaviour {
public Color rayColor = Color.red;
public List path_objs = new List();
Transform[] theArray;
void OnDrawGizmos(){
Gizmos.color = rayColor;
theArray = GetComponentsInChildren();
path_objs.Clear();
foreach(Transform path_obj in theArray){
if(path_obj != this.transform)
path_objs.Add(path_obj);
}
for(int i = 0;i0){
Vector3 previous = path_objs[i-1].position;
Gizmos.DrawLine(previous,position);
Gizmos.DrawWireSphere(position, 0.3f);
}
}
}
}
using UnityEngine;
using System.Collections;
public class FollowPath : MonoBehaviour {
public bool StartFollow = false;
public EditorPathScript PathToFollow;
public int CurrentWayPointID = 0;
public float Speed;//移动速度
public float reachDistance = 0f;//里路径点的最大范围
public string PathName;//跟随路径的名字
private string LastName;
private bool ChangePath = true;
void Start () {
}
void Update () {
if (!StartFollow)
return;
if (ChangePath)
{
PathToFollow = GameObject.Find(PathName).GetComponent();
ChangePath = false;
}
if (LastName != PathName)
{
ChangePath = true;
}
LastName = PathName;
float distance = Vector3.Distance(PathToFollow.path_objs[CurrentWayPointID].position, transform.position);
//transform.Translate(PathToFollow.path_objs[CurrentWayPointID].position * Time.deltaTime * Speed, Space.Self);
transform.position = Vector3.MoveTowards(transform.position, PathToFollow.path_objs[CurrentWayPointID].position, Time.deltaTime * Speed);
if (distance <= reachDistance)
{
CurrentWayPointID++;
}
if (CurrentWayPointID >= PathToFollow.path_objs.Count)
{
CurrentWayPointID = 0;
}
}
}
沒有留言:
張貼留言