您好,登錄后才能下訂單哦!
如何在Unity3D中使用撤回命令?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
首先肯定要創建命令的基類,
public class BaseCommand { //執行命令 public virtual void ExcuteCommand() { } //撤銷命令 public virtual void RevocationCommand() { } }
因為我們控制物體的類似移動改變方式不同,有可能是直接移動的,有可能是用的dotween來操作移動,所以我們的執行命令函數可能對于我們沒有實現的必要。下面我們要創建一個用來管理命令的腳本,供我們添加和移除命令,同時這個腳本我們給設置為單例,可供全局調用。如下:
public class CommandManager : MonoBehaviour { public static CommandManager Instance = null; //管理命令 private Stack<BaseCommand> commandStack = new Stack<BaseCommand>(); private void Awake() { Instance = this; } //增加命令 public void AddCommand(BaseCommand baseCommand) { commandStack.Push(baseCommand); } //移除命令 并且撤銷一步操作 public void RemoveCommand() { if(commandStack.Count>0) { BaseCommand baseCommand = commandStack.Pop(); baseCommand.RevocationCommand(); } } }
有個命令基類,有了管理類,下面我們就要對不同命令進行專門的功能實現了。
一.移動類命令
//保存模型的位置 角度 大小信息 public class TransformCommand : BaseCommand { private Transform target; private Vector3 pos; private Vector3 rota; private Vector3 scale; private Transform parent; //我們在構造函數里直接傳進來我們改變狀態前的Transform信息 public TransformCommand(Transform target, Vector3 pos, Vector3 rota, Vector3 scale,Transform parent) { this.target = target; this.pos = pos; this.rota = rota; this.scale = scale; this.parent = parent; } public override void ExcuteCommand() { base.ExcuteCommand(); } public override void RevocationCommand() { target.SetParent(parent); target.transform.localPosition = pos; target.transform.localEulerAngles = rota; target.transform.localScale = scale; } }
下面是我們寫的測試腳本掛在到攝像頭上,
public class CameraMove : MonoBehaviour { // Update is called once per frame void Update () { if(Input.GetKeyDown(KeyCode.W)) { TransformCommand cmd = new TransformCommand(transform,transform.localPosition, transform.localEulerAngles,transform.localScale,null); CommandManager.Instance.AddCommand(cmd); transform.Translate(Vector3.forward,Space.Self); } } }
還需要寫一個輸入的類來調用撤退命令,代碼如下:
public class Test : MonoBehaviour { private void Update() { if(Input.GetKeyDown(KeyCode.Escape)) { CommandManager.Instance.RemoveCommand(); } } }
二.UI類用戶控制改變狀態
下面以InputField為例,介紹UI交互類的撤退命令,這個要比普通的麻煩一些。我找了官方文檔好久也沒發現值改變前得回掉函數,所以只能自己來實現了。首先我們要自己寫一個腳本用來記錄改變之前的值。掛載在場景里的InputField上。代碼如下:
public class MyInputField : MonoBehaviour,IPointerClickHandler { private InputField input; private string preString;//用來記錄改變前得值 private bool IsValueChange = false;//判斷值是否發生改變 private bool IsClick = false;//用來判斷InputField是否被選中交互 private void Awake() { input = GetComponent<InputField>(); input.onValueChanged.AddListener(delegate { IsValueChange=true; }); input.onEndEdit.AddListener(OnEndEditCallBck); } //結束編輯得回調函數 void OnEndEditCallBck(string content) { IsClick = false; //如果值沒變 直接返回 沒必要增加命令 if (IsValueChange == false) return; InputFieldCommand cmd = new InputFieldCommand(input,preString); CommandManager.Instance.AddCommand(cmd); } //當被點擊時,我們的UI組件被交互 有被更改值得可能 所以要記錄當前值 public void OnPointerClick(PointerEventData eventData) { Debug.Log("點擊"); if (IsClick) return; preString = input.text; IsClick = true; } } public class InputFieldCommand : BaseCommand { private InputField targetInput; private string content; public InputFieldCommand(InputField inputField,string content) { this.targetInput = inputField; this.content = content; } public override void RevocationCommand() { base.RevocationCommand(); targetInput.text = content; } }
上面就是在用戶對InputField輸入內容改變時自動記錄上一步得命令。對于其他得UI組件類似Toggle Slider同樣適用。
三.銷毀生成的物體
我們在當前一步實例化很多物體,返回上一步就需要銷毀所有實例化的物體。這里我們不建議直接銷毀,而是利用對象池技術進行回收,還節約性能。對象池技術博客地址:點擊打開鏈接 代碼如下:
public class DestoryCommand : BaseCommand { private List<GameObject> objects; public DestoryCommand(List<GameObject> objects) { this.objects = objects; } public override void RevocationCommand() { for(int i=0;i< objects.Count;i++) { //利用對象池技術回收物體 這里就不寫了 因為還要把對象池的腳本添加進來 } } }
關于如何在Unity3D中使用撤回命令問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。