脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DetectCollision : MonoBehaviour
{
public Transform player;
public Transform target;
public Text currPosDistanceUiText;
public bool rotateAutomatic = false;
public bool turnOnOffPlayerAnimator = false;
float timeElapsed = 0;
float lerpDuration = 3;
float startValue = 1;
float endValue = 0;
float valueToLerp = 0;
private Animator playerAnimator;
private bool entered = false;
private bool prevFacing = false;
private bool stopped = false;
private bool move = true;
private bool rot = false;
private Vector3 currPos;
// Start is called before the first frame update
void Start()
{
playerAnimator = player.GetComponent<Animator>();
if (turnOnOffPlayerAnimator)
playerAnimator.enabled = false;
}
// Update is called once per frame
void Update()
{
var currFacing = IsFacing(target);
if (currFacing != prevFacing)
{
// here you switched from facing to not facing or vise verca.
timeElapsed = 0;
}
prevFacing = currFacing;
var distance = Vector3.Distance(player.position, target.position);
if (IsFacing(target))
{
if (entered && distance > 30 && move)
{
if (timeElapsed < lerpDuration)
{
valueToLerp = Mathf.Lerp(startValue, endValue, timeElapsed / lerpDuration);
playerAnimator.SetFloat("Forward", valueToLerp);
timeElapsed += Time.deltaTime;
}
playerAnimator.SetFloat("Forward", valueToLerp);
stopped = true;
valueToLerp = 0;
}
if (move == false)
{
playerAnimator.SetFloat("Forward", 0);
}
if (playerAnimator.GetFloat("Forward") == 0 && stopped)
{
move = false;
rot = true;
currPos = player.position;
Debug.Log("Player current position when valueToLerp value is 0 : " + currPos);
}
}
else
{
if (rotateAutomatic == false)
{
if (valueToLerp < 0.9f)
{
if (timeElapsed < lerpDuration)
{
valueToLerp = Mathf.Lerp(endValue, startValue, timeElapsed / lerpDuration);
playerAnimator.SetFloat("Forward", valueToLerp);
timeElapsed += Time.deltaTime;
}
playerAnimator.SetFloat("Forward", valueToLerp);
}
}
var dist = Vector3.Distance(player.position, currPos);
currPosDistanceUiText.text = dist.ToString();
if (dist > 2)
{
move = true;
}
}
if (rotateAutomatic && rot)
{
StartCoroutine(ScaleOverSeconds(new Vector3(0.3f,0.3f,0.3f),
new Vector3(0,90,0), new Vector3(player.localPosition.x + 20,0,0) , 5));
rot = false;
//StartCoroutine(AnimateRotationTowards(player, Quaternion.Euler(0, 180, 0), 5f));
/*player.rotation = Quaternion.Lerp(player.rotation, Quaternion.Euler(0, 180, 0), Time.time * 0.0003f);
if (timeElapsed < lerpDuration)
{
valueToLerp = Mathf.Lerp(endValue, startValue, timeElapsed / lerpDuration);
playerAnimator.SetFloat("Forward", valueToLerp);
timeElapsed += Time.deltaTime;
}
playerAnimator.SetFloat("Forward", valueToLerp);*/
}
if (turnOnOffPlayerAnimator)
{
playerAnimator.enabled = false;
}
else
{
playerAnimator.enabled = true;
}
}
private void OnTriggerEnter(Collider other)
{
entered = true;
Debug.Log("Entered !");
}
private void OnTriggerExit(Collider other)
{
entered = false;
Debug.Log("Exited !");
}
private bool IsFacing(Transform target)
{
Vector3 forward = player.TransformDirection(Vector3.forward);
Vector3 toTarget = target.position - player.position;
return Vector3.Dot(forward, toTarget) > 0;
}
private System.Collections.IEnumerator AnimateRotationTowards(Transform target, Quaternion rot, float dur)
{
rotateAutomatic = true;
float t = 0f;
Quaternion start = target.rotation;
while (t < dur)
{
target.rotation = Quaternion.Slerp(start, rot, t / dur);
yield return null;
t += Time.deltaTime;
}
target.rotation = rot;
}
public IEnumerator ScaleOverSeconds(Vector3 scaleTo, Vector3 rotateTo, Vector3 moveTo, float seconds)
{
float elapsedTime = 0;
Vector3 startingScale = player.localScale;
Vector3 startingRotation = player.localEulerAngles;
Vector3 startingPosition = player.localPosition;
while (elapsedTime < seconds)
{
player.localScale = Vector3.Lerp(startingScale, scaleTo, (elapsedTime / seconds));
player.localEulerAngles = Vector3.Lerp(startingRotation, rotateTo, (elapsedTime / seconds));
player.localPosition = Vector3.Lerp(startingPosition, moveTo, (elapsedTime / seconds));
elapsedTime += Time.deltaTime;
yield return null;
}
player.localScale = scaleTo;
player.localEulerAngles = rotateTo;
player.localPosition = moveTo;
}
}
我在第 73 行将 rot 设置为 true。
然后
public IEnumerator ScaleOverSeconds(Vector3 scaleTo, Vector3 rotateTo, Vector3 moveTo, float seconds)
{
float elapsedTime = 0;
Vector3 startingScale = player.localScale;
Vector3 startingRotation = player.localEulerAngles;
Vector3 startingPosition = player.localPosition;
//If you want, you can change axis of rotation or angle or everything you want. But what I do - I rotate by Y-axis for 180 degrees
while (elapsedTime < seconds)
{
player.localScale = Vector3.Lerp(startingScale, scaleTo, (elapsedTime / seconds));
player.localEulerAngles = Vector3.Lerp(startingRotation, rotateTo, (elapsedTime / seconds));
player.localPosition = Vector3.Lerp(startingPosition, moveTo, (elapsedTime / seconds));
elapsedTime += Time.deltaTime;
yield return null;
}
player.localScale = scaleTo;
player.localEulerAngles = rotateTo;
player.localPosition = moveTo;
}
它一直在缩放、旋转、移动,但出于某种原因,当它完成移动时,玩家就在原地。
在 ScaleOverSeconds 中它工作正常,它带有缩放和旋转,只有在添加移动部分后才开始在最后出现口吃。
播放器已附加此组件:
这个游戏对象是一个四边形,这是玩家进入时的进入区域检测,这个脚本附加到四边形上: