我正在為我的unity游戲使用狀態模式。我有三個狀態:HappyState、SurprisedState和SadState。HappyState是默認狀態。我想讓角色通過點擊滑鼠左鍵跳躍并進入驚訝狀態。在進入驚訝狀態時,需要做一些作業,我把這些作業定義為一個無效的事件,但它沒有發揮作用!
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using System;
public class CapsuleScript : MonoBehaviour
{
public event Action SliderAction;
public Slider slider;
public Text stateText;
public GameObject hands;
public Rigidbody rb;
public CapsuleBasicStates currentstate;
public readonly HappyState happyState = new HappyState()。
public readonly SadState sadState = new SadState()。
public readonly SurprisedState surprisedState = new SurprisedState();
public SpriteRenderer renderer;
public Sprite happysprite, sadsprite, surprisedsprite;
//在第一幀更新之前呼叫Start。
void Start()
{
slider.value = 0;
renderer = GetComponentInChildren<SpriteRenderer>()。
rb = GetComponent<Rigidbody>()。
TransitionToState(happyState)。
}
public void OnCollisionEnter(Collision other){
currentstate.OnCollisionEnter(this)。
}
//更新在每一幀被呼叫一次。
void Update()
{
currentstate.Update(this)。
}
public void SetSprite(Sprite sprite)。
{
renderer.sprite = sprite;
}
public void TransitionToState(CapsuleBasicStates state) ?
{
currentstate = state;
currentstate.EnterState(this)。
}
public IEnumerator SliderHandler()
{
yield return new WaitForSeconds(1f);
slider.value =1;
StartCoroutine(SliderHandler())。
}
public void IEHandler()
{
StartCoroutine(SliderHandler())。
}
這里是SurprisedState腳本
。using System.Collections;
using System.Collections.Generic;
public class SurprisedState : CapsuleBasicStates
{
public override void EnterState(CapsuleScript player)
{
player.SetSprite(player.urprisingsprite)。
player.stateText.text = player.urprisingState.ToString()。
player.slider.gameObject.SetActive(true)。
player.SliderAction = player.IEHandler。
}
public override void OnCollisionEnter(CapsuleScript player)。
{
//player.TransitionToState(player.happyState);
}
public override void Update(CapsuleScript player)。
{
if(player.slider.value ==20)
{
player.SliderAction -= player.IEHandler;
player.TransitionToState(player.happyState)。
}
}
}
HappyState腳本
using System.Collections;
using System.Collections.Generic;
public class HappyState : CapsuleBasicStates
{
public override void EnterState(CapsuleScript player)
{
player.SetSprite(player.happysprite)。
player.stateText.text = player.happyState.ToString()。
player.hands.SetActive(false)。
}
public override void OnCollisionEnter(CapsuleScript player)
{
}
public override void Update(CapsuleScript player)。
{
if(Input.GetButton("Fire1"/span>)
{
player.rb.AddForce(Vector3.up * 150f) 。
player.TransitionToState(player.surprisingState)。
}
if(Input.GetButton("Fire2"/span>)
{
player.rb.AddForce(Vector3.up *250f) 。
player.TransitionToState(player.sadState)。
}
}
}
uj5u.com熱心網友回復:
在我發布我的解決方案之前,有幾個要點:
BaseSate.cs
[System.Serializable]
public abstract class BaseState
{
public enum PlayerStates { HappyState = 0, SurprisedState = 1 }
public abstract PlayerStates PlayerState { get; }
public abstract void EnterState(PlayerScript playerScript) 。
public abstract void UpdateState();
public abstract void ExitState()。
HappySate.cs
using UnityEngine;
[System.Serializable]
public class HappyState : BaseState
{
public override PlayerStates PlayerState => PlayerStates.HappyState。
private PlayerScript _playerScript;
public override void EnterState(PlayerScript playerScript)
{
_playerScript = playerScript;
Debug.Log($"Entered {PlayerState}") 。
}
public override void UpdateState()
{
if (Input.GetButtonDown("Fire1"/span>)
{
_playerScript.ChangeState(new SurprisedState())。
}
}
public override void ExitState()
{
Debug.Log($"Exited {PlayerState}") 。
}
SurprisedState.cs
using UnityEngine;
[System.Serializable]
public class SurprisedState : BaseState
{
public override PlayerStates PlayerState => PlayerStates.SurprisedState;
private PlayerScript _playerScript;
public override void EnterState(PlayerScript playerScript)
{
_playerScript = playerScript。
///訂閱sliderAction on enter[/span]。
playerScript.playerSliderAction = OnSliderChange;
Debug.Log($"進入{PlayerState}"/span>)。
}
private void OnSliderChange。 title">OnSliderChange(float sliderValue)。
{
//在比較時使用Mathf.Approximately而不是===。
//浮點數。 //浮點數。
if (Mathf.Approximately(sliderValue, 20f)
{
_playerScript.ChangeState(new HappyState())。
}
}
public override void UpdateState() { } new HappyState.
public override void ExitState()
{
///取消退出時對sliderAction的訂閱。
_playerScript.playerSliderAction -= OnSliderChange;
Debug.Log($"Exited {PlayerState}") 。
}
PlayerScript.cs
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
public class PlayerScript : MonoBehaviour
{
[SerializeField]。
private SpriteRenderer playerRenderer;
[SerializeField[/span>]
private Sprite[] playerStateSprites;
[SerializeField[/span>]
private Slider playerSlider;
public UnityAction<float> playerSliderAction;
private BaseState _currentState。
private void Awake()
{
Initialize()。
}
private void Update()
{
_currentState.UpdateState()。
}
private void Initialize()
{
ChangeState(new HappyState())。
//使用滑塊onValueChanged而不是檢查滑塊。
///每一幀的值。。
///當值被改變時呼叫unity action。
playerSlider.onValueChanged.AddListener(sliderValue =>
{
playerSliderAction?.Invoke(sliderValue)。
});
}
public void ChangeState(BaseState newState)
{
//僅當狀態不同時才改變。
//與之前的狀態不同。
if (_currentState == newState)
{
return;
}
_currentState?.ExitState()。
_currentState = newState。
_currentState.EnterState(this)。
playerRenderer.sprite = playerStateSprites[(int)newState.PlayerState]。
Debug.Log($"Current State : {_currentState.PlayerState}")。)
}
PlayerScript檢查器視圖
執行概述gif:
https://gfycat.com/grimflowerycollardlizard
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/312672.html
標籤:

