前言
之前写的代码中由Controller控制动作,现在我们将其中对动作的控制抽离出来。
Action类
创建一个Action类用来管理所有游戏事物的动作
依据课件设计

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PriestAndDevil;
public class SSAction : ScriptableObject //动作基类
{
public bool enable = true;
public bool destroy = false;
public GameObject gameobject{ get; set;}
public Transform transform{ get; set;}
public ISSActionCallback callback{get; set;}
protected SSAction() {}
public virtual void Start()
{
throw new System.NotImplementedException();
}
public virtual void Update()
{
throw new System.NotImplementedException();
}
}
public class CCMoveToAction : SSAction //动作实现
{
public Vector3 target;
public float speed;
public static CCMoveToAction GetSSAction(Vector3 target, float speed)
{
CCMoveToAction action = ScriptableObject.CreateInstance<CCMoveToAction>();
action.target = target;
action.speed = speed;
return action;
}
public override void Update()
{
this.transform.position = Vector3.MoveTowards(this.transform.position, target, speed * Time.deltaTime);
if (this.transform.position == target)
{
this.destroy = true;
this.callback.SSActionEvent(this);
}
}
public override void Start()
{}
}
public class CCSequenceAction : SSAction, ISSActionCallback //动作组合实现复杂动作
{
public List<SSAction> sequence;
public int repeat = -1;
public int start = 0;
public static CCSequenceAction GetSSAction(int repeat, int start, List<SSAction> sequence)
{
CCSequenceAction action = ScriptableObject.CreateInstance<CCSequenceAction>();
action.repeat = repeat;
action.sequence = sequence;
action.start = start;
return action;
}
public override void Update()
{
if (sequence.Count == 0) return;
if (start < sequence.Count)
{
sequence[start].Update();
}
}
//接口定义
public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,int intParam = 0, string strParam = null, Object objectParam = null)
{
source.destroy = false;
this.start++;
if (this.start >= sequence.Count)
{
this.start = 0;
if (repeat > 0)
repeat--;
if (repeat == 0)
{
this.destroy = true;
this.callback.SSActionEvent(this);
}
}
}
public override void Start()
{
foreach (SSAction action in sequence)
{
action.gameobject = this.gameobject;
action.transform = this.transform;
action.callback = this;
action.Start();
}
}
void OnDestroy()
{}
}
public enum SSActionEventType : int { Started, Competeted }
public interface ISSActionCallback
{
void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,int intParam = 0, string strParam = null, Object objectParam = null);
}
//动作管理器基类
public class SSActionManager : MonoBehaviour, ISSActionCallback
{
private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();
private List<SSAction> waitingAdd = new List<SSAction>();
private List<int> waitingDelete = new List<int>();
protected void Update()
{
foreach (SSAction ac in waitingAdd)
{
actions[ac.GetInstanceID()] = ac;
}
waitingAdd.Clear();
foreach (KeyValuePair<int, SSAction> kv in actions)
{
SSAction ac = kv.Value;
if (ac.destroy)
{
waitingDelete.Add(ac.GetInstanceID());
}
else if (ac.enable)
{
ac.Update();
}
}
foreach (int key in waitingDelete)
{
SSAction ac = actions[key];
actions.Remove(key);
Destroy(ac);
}
waitingDelete.Clear();
}
public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager)
{
action.gameobject = gameobject;
action.transform = gameobject.transform;
action.callback = manager;
waitingAdd.Add(action);
action.Start();
}
protected void Start()
{
}
public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,
int intParam = 0, string strParam = null, Object objectParam = null){}
}
//动作管理器实现
public class CCActionManager:SSActionManager
{
private CCSequenceAction moverole_act;
private CCMoveToAction moveboat_act;
public Controller controller;
protected new void Start()
{
controller = SSDirector.GetInstance().CurrentScenceController as Controller;
controller.action_manager = this;
}
public void MoveBoat(GameObject boat,Vector3 target,float speed)
{
moveboat_act = CCMoveToAction.GetSSAction(target,speed);
this.RunAction(boat,moveboat_act,this);
}
public void MoveRole(GameObject role,Vector3 middle,Vector3 end,float speed)
{
SSAction move_to_middle = CCMoveToAction.GetSSAction(middle,speed);
SSAction move_to_end = CCMoveToAction.GetSSAction(end,speed);
List<SSAction> act_list = new List<SSAction> {move_to_middle,move_to_end};
moverole_act = CCSequenceAction.GetSSAction(1,0,act_list);
this.RunAction(role,moverole_act,this);
}
}
Controller
Controller更改如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PriestAndDevil;
public class Controller : MonoBehaviour,ISceneController,IUserAction
{
public Side left_side;//左岸为起点起点
public Side right_side;//终点
public Boat boat;
public GameObject river;
private List<Role> role_array;
UserGUI gui;
public Judge judge;
public CCActionManager action_manager;
void Start()
{
SSDirector director = SSDirector.GetInstance();
director.CurrentScenceController = this;
gui = gameObject.AddComponent<UserGUI>() as UserGUI;
LoadResources();
}
public void LoadResources()
{
left_side = new Side("left");
right_side = new Side("right");
boat = new Boat();
role_array = new List<Role>();
river = Instantiate(Resources.Load("Prefabs/Water",typeof(GameObject)),new Vector3(0, -0.5F, -0.49F), Quaternion.identity) as GameObject;
judge = new Judge();
action_manager = gameObject.AddComponent<CCActionManager>() as CCActionManager;
for (int i = 0; i < 3; i++)
{
Role role = new Role("priest");
role.SetName("priest" + i);
role.SetPosition(left_side.GetEmptyPosition());
role.GoSide(left_side);
left_side.AddRole(role);
role_array.Add(role);
}
for (int i = 0; i < 3; i++)
{
Role role = new Role("devil");
role.SetName("devil" + i);
role.SetPosition(left_side.GetEmptyPosition());
role.GoSide(left_side);
left_side.AddRole(role);
role_array.Add(role);
}
}
public void MoveBoat()
{
if (boat.IsEmpty() || gui.sign != 0)
return;
action_manager.MoveBoat(boat.GetBoat(),boat.GetTargetPos(),boat.speed);
gui.sign = judge.Check();
}
public void MoveRole(Role role)
{
if (gui.sign != 0)
return;
if (role.IsOnBoat())
{
Side Side;
if (boat.GetBoatSign() == 1)
Side = left_side;
else
Side = right_side;
boat.DeleteRoleByName(role.GetName());
Vector3 end = Side.GetEmptyPosition();
Vector3 middle = new Vector3(role.GetRole().transform.position.x, end.y, end.z);
action_manager.MoveRole(role.GetRole(),middle,end,role.speed);
role.GoSide(Side);
Side.AddRole(role);
}
else
{
Side Side = role.GetSide();
if (boat.GetEmptyNumber() == -1 || Side.GetSideFlag() != boat.GetBoatSign())
return;
Side.DeleteRoleByName(role.GetName());
Vector3 end = boat.GetEmptyPosition();
Vector3 middle = new Vector3(end.x,role.GetRole().transform.position.y,end.z);
action_manager.MoveRole(role.GetRole(),middle,end,role.speed);
role.GoBoat(boat);
boat.AddRole(role);
}
gui.sign = judge.Check();
if (gui.sign == 1)
{
}
}
public void Restart()
{
left_side.Reset();
right_side.Reset();
boat.Reset();
for (int i = 0; i < role_array.Count; i++)
{
role_array[i].Reset();
}
if (gui.sign == 1)
{
}
}
public int Check()
{
return 1;
}
}
其余保持基本不变,效果和之前一致
本文介绍了一个基于Unity的游戏动作管理系统的设计与实现。系统包括动作基类SSAction及其子类如CCMoveToAction和CCSequenceAction,用于实现角色和船只的移动等游戏内行为。通过动作管理器SSActionManager和其子类CCActionManager来调度这些动作。
1584

被折叠的 条评论
为什么被折叠?



