首页>Game>source

我正在用Unity制作2D平台游戏.最近,我实施了压力垫系统.基本上,当玩家触发打击垫时,应该打开附近的一扇门.系统正常运行,但唯一的问题是玩家停留在打击板上时, OpenWhenOn 动画(用于开门的空闲动画)没有播放.我想让此播放器一直保持播放状态,只要玩家在打击板上就可以,如果它退出触发器,则 DoorClosing 应该播放动画.我写这段代码主要是为了播放动画,但是它不起作用,我得到了 Null Reference 一直出错。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class PressurePad : MonoBehaviour
{
    private Animator anim;
    public UnityEvent OnActivate;
    public UnityEvent OnDeactivate;
    public GameObject door;
    public float deactivationDelay = 2f;
    int objectsInContact;
    Coroutine waitingToDeactivate;

    IEnumerator Timer()
    {
        yield return new WaitForSeconds(deactivationDelay);
        // Tell our listeners we're switched OFF.
        if (OnDeactivate != null)
            OnDeactivate.Invoke();
        // Return to ready-to-activate state:
        waitingToDeactivate = null;
    }
    void OnTriggerEnter2D(Collider2D other)
    {
       
        if (other.CompareTag("Player"))
         
        {
            anim.Play("OpenWhenOn");
        }
        door.GetComponent<Animator>().Play("OpenWhenOn");
       
        objectsInContact++;
        // Pressure pad pressed.
        if (objectsInContact == 1)
        {
            if (waitingToDeactivate != null)
            {
                // Cancel deactivation timer. 
                StopCoroutine(waitingToDeactivate);
                waitingToDeactivate = null;
            }
            else if (OnActivate != null)
            {
                // Tell our listeners we're switched ON.
                OnActivate.Invoke();
            }
        }
    }
    void OnTriggerExit2D(Collider2D other)
    {
        objectsInContact--;
        // Pressure pad released.
        if (objectsInContact == 0)
        {
            // Start a delay before telling anyone.
            waitingToDeactivate = StartCoroutine(Timer());
        }
    }
}

This is my Animator Controller. HasExitTime 禁用所有过渡. OpenWhenOn之间过渡的条件 和 DoorClosing 设置为false。

最新回答
  • 2020-12-27
    1 #

    我建议您做这样的事情:

    使用4种动画状态设置您的Animator控制图:

      Opening

      Open (single frame with the door stationary in its open position)

      Closing

      Closed (single frame with door stationary in its closed position)

    向图形添加两个"触发器"参数:

      "StartOpening"

      "StartClosing"

    添加过渡:

      from Opening to Open with "HasExitTime" so it transitions to the Open state when the Opening animation is finished, holding the door open

      from Closing to Closed with "HasExitTime" so it transitions to the Closed state when the Closing animation is finished, holding the door shut

      from Open/Opening to Closing with a condition on "StartClosing"

      from Closed/Closing to Opening with a condition on "StartOpening"

    在PressureSwitch上连接UnityEvents:

      OnActivate should call your door's Animator.SetTrigger() 方法,其参数为" StartOpening"

        OnDeactivate should call your door's Animator.SetTrigger() 方法,其参数为" StartClosing"

        这使您无需在压力开关和门之间进行硬耦合就可以对门的开关行为进行接线,甚至不需要自定义门脚本!

        当然,您也可以写一个 DoorControl 通过让门管理自己的动画制作者状态来稍微简化Inspector设置的脚本:

        [RequireComponent(typeof(Animator))]
        public class DoorControl {
            [SerializeField, HideInInspector]
            Animator _animator;
            [SerializeField]
            bool _isOpen;
            void OnValidate() {
                _animator = GetComponent<Animator>();
                SetOpen(_isOpen);
            }
            void Start() {
                SetOpen(_isOpen);
            }
            public void Open() {
                SetOpen(true);
            }
            public void Close() {
                SetOpen(false);
            }
            public void SetOpen(bool open) {
                _isOpen = open;
                _animator.SetBool("Open", _isOpen);
            }
        }
        

        现在您可以使用一个布尔值而不是两个触发器来控制您的门( SetBool 方法需要两个参数,因此我们无法通过检查器将其连接起来).挂起事件要容易一些-您可以致电 DoorControl.Open()DoorControl.Close() 无需键入动画参数的确切名称-该知识被委派给了 DoorControl ,使您的设置减少耦合。

  • 2020-12-27
    2 #

    我想您可以

    this.gameObject.GetComponent<Animator>().Play("DoorOpening");
    

    所以它将播放并循环播放。

    如果您更类似使用动画器本身,还可以复制开门动画并为其添加新的触发器,因此当您触发它时,它会一直存在,或者根据您的动画器而改变

    例如,如果您在 OnTriggerEnter()中有压力垫 您需要访问门的Animator,然后使用我的脚本:

    public Animator anim;
    
       void OnTriggerEnter(Collision other)
    {
      if(other.compareTag("Player")
    anim.Play("DoorOpening");
    }
    

    这只是一个示例,但是您可以在任何地方使用它

  • 2020-12-27
    3 #

    我看不到任何将条件设置为true的地方都可以在 DoorOpening之间移动 和 OpenWhenOn 动画.尝试删除 DoorOpening之间的过渡条件 和 OpenWhenOn ,如果没有条件,那就 OpenWhenOn 应该在 DoorOpening之后自动播放 动画播放。

  • networking:通过网络Unity同步运行的代码
  • unity:计算添加有噪声的网格法线