为什么玩家移动后会卡顿?

时间:2021-03-28 18:31:47

标签: c# unity3d

脚本:

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 中它工作正常,它带有缩放和旋转,只有在添加移动部分后才开始在最后出现口吃。

播放器已附加此组件:

player

这个游戏对象是一个四边形,这是玩家进入时的进入区域检测,这个脚本附加到四边形上:

quad

0 个答案:

没有答案