Unity3D撤回命令開發(fā)詳解
本文實(shí)例為大家分享了Unity3D撤回命令功能開發(fā),供大家參考,具體內(nèi)容如下
在類似操作考核的項(xiàng)目中我們經(jīng)常會(huì)遇到回到上一步的需求。所以我們有必要對(duì)每一個(gè)狀態(tài)點(diǎn)的所有參與交互的物體的狀態(tài)進(jìn)行記錄。好了,下面就是代碼的實(shí)現(xiàn):
首先肯定要?jiǎng)?chuàng)建命令的基類,
public class BaseCommand
{
//執(zhí)行命令
public virtual void ExcuteCommand() { }
//撤銷命令
public virtual void RevocationCommand() { }
}
因?yàn)槲覀兛刂莆矬w的類似移動(dòng)改變方式不同,有可能是直接移動(dòng)的,有可能是用的dotween來操作移動(dòng),所以我們的執(zhí)行命令函數(shù)可能對(duì)于我們沒有實(shí)現(xiàn)的必要。下面我們要?jiǎng)?chuàng)建一個(gè)用來管理命令的腳本,供我們添加和移除命令,同時(shí)這個(gè)腳本我們給設(shè)置為單例,可供全局調(diào)用。如下:
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();
}
}
}
有個(gè)命令基類,有了管理類,下面我們就要對(duì)不同命令進(jìn)行專門的功能實(shí)現(xiàn)了。
一.移動(dòng)類命令
//保存模型的位置 角度 大小信息
public class TransformCommand : BaseCommand
{
private Transform target;
private Vector3 pos;
private Vector3 rota;
private Vector3 scale;
private Transform parent;
//我們?cè)跇?gòu)造函數(shù)里直接傳進(jìn)來我們改變狀態(tài)前的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;
}
}
下面是我們寫的測(cè)試腳本掛在到攝像頭上,
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);
}
}
}
還需要寫一個(gè)輸入的類來調(diào)用撤退命令,代碼如下:
public class Test : MonoBehaviour {
private void Update()
{
if(Input.GetKeyDown(KeyCode.Escape))
{
CommandManager.Instance.RemoveCommand();
}
}
}
二.UI類用戶控制改變狀態(tài)
下面以InputField為例,介紹UI交互類的撤退命令,這個(gè)要比普通的麻煩一些。我找了官方文檔好久也沒發(fā)現(xiàn)值改變前得回掉函數(shù),所以只能自己來實(shí)現(xiàn)了。首先我們要自己寫一個(gè)腳本用來記錄改變之前的值。掛載在場(chǎng)景里的InputField上。代碼如下:
public class MyInputField : MonoBehaviour,IPointerClickHandler
{
private InputField input;
private string preString;//用來記錄改變前得值
private bool IsValueChange = false;//判斷值是否發(fā)生改變
private bool IsClick = false;//用來判斷InputField是否被選中交互
private void Awake()
{
input = GetComponent<InputField>();
input.onValueChanged.AddListener(delegate { IsValueChange=true; });
input.onEndEdit.AddListener(OnEndEditCallBck);
}
//結(jié)束編輯得回調(diào)函數(shù)
void OnEndEditCallBck(string content)
{
IsClick = false;
//如果值沒變 直接返回 沒必要增加命令
if (IsValueChange == false) return;
InputFieldCommand cmd = new InputFieldCommand(input,preString);
CommandManager.Instance.AddCommand(cmd);
}
//當(dāng)被點(diǎn)擊時(shí),我們的UI組件被交互 有被更改值得可能 所以要記錄當(dāng)前值
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("點(diǎn)擊");
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;
}
}
上面就是在用戶對(duì)InputField輸入內(nèi)容改變時(shí)自動(dòng)記錄上一步得命令。對(duì)于其他得UI組件類似Toggle Slider同樣適用。
三.銷毀生成的物體
我們?cè)诋?dāng)前一步實(shí)例化很多物體,返回上一步就需要銷毀所有實(shí)例化的物體。這里我們不建議直接銷毀,而是利用對(duì)象池技術(shù)進(jìn)行回收,還節(jié)約性能。對(duì)象池技術(shù)博客地址:點(diǎn)擊打開鏈接 代碼如下:
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++)
{
//利用對(duì)象池技術(shù)回收物體 這里就不寫了 因?yàn)檫€要把對(duì)象池的腳本添加進(jìn)來
}
}
}
這個(gè)命令是在我們實(shí)例化物體后才能增加。其實(shí)就是把實(shí)例化的物體加入到List數(shù)組然后傳入一個(gè)新聲明的DestoryCommand構(gòu)造函數(shù)中。以上效果圖如下:

希望本博客對(duì)你有幫助!
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#創(chuàng)建一個(gè)小型Web Server(Socket實(shí)現(xiàn))
這篇文章主要介紹了關(guān)于C#利用Socket實(shí)現(xiàn)創(chuàng)建一個(gè)小型Web Server的相關(guān)資料,文中通過示例代碼介紹的很詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2017-02-02
Unity實(shí)現(xiàn)答題系統(tǒng)的示例代碼
這篇文章主要和大家分享了利用Unity制作一個(gè)答題系統(tǒng)的示例代碼,文中的實(shí)現(xiàn)方法講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定的幫助,需要的可以參考一下2022-05-05
VsCode使用EmmyLua插件調(diào)試Unity工程Lua代碼的詳細(xì)步驟
這篇文章主要介紹了VsCode使用EmmyLua插件調(diào)試Unity工程Lua代碼,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
C#根據(jù)年月日計(jì)算星期幾的函數(shù)小例子
這篇文章介紹了C#根據(jù)年月日計(jì)算星期幾的函數(shù)小例子,有需要的朋友可以參考一下2013-07-07
C#實(shí)現(xiàn)的自定義郵件發(fā)送類完整實(shí)例(支持多人多附件)
這篇文章主要介紹了C#實(shí)現(xiàn)的自定義郵件發(fā)送類,具有支持多人多附件的功能,涉及C#郵件操作的相關(guān)技巧,需要的朋友可以參考下2015-12-12
WPF實(shí)現(xiàn)炫酷的界面交互效果的代碼詳解
在當(dāng)今競(jìng)爭(zhēng)激烈的軟件市場(chǎng)中,用戶界面的交互體驗(yàn)至關(guān)重要,一個(gè)擁有炫酷動(dòng)畫特效的應(yīng)用程序,不僅能吸引用戶的注意力,還能顯著提升用戶與界面的交互流暢度和愉悅感,本文將深入剖析WPF動(dòng)畫特效的各個(gè)方面,通過大量詳細(xì)的代碼示例和對(duì)關(guān)鍵概念的深入解釋2025-02-02

