前言
中山大学数据科学与计算机学院3D游戏课程学习记录博客。
游戏代码:gitee
游戏视频:bilibili
参考师兄的博客: 师兄博客
游戏要求
- 实现动作分离,用动作控制器控制移动
- 实现Check类
游戏实现
实现Check类
直接把原来FirstController.cs中的check函数拉出改成Check类即可。
实现动作分离
实现动作分离需要进行一定的程序设计。
- 接口ISSActionCallback和状态SSActionEventType:
接口定义了一个函数,为了实现动作的调度和动作完成消息的传递,与运动有关的类都要实现这个接口;
状态定义了动作的开始状态和结束状态。
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
);
}
- 实现动作基类SSAction:
动作基类记录了动作是否被完成,动作来自哪个对象等信息。
每一个基类对象都是一个动作。
动作基类只允许交互动作产生,不允许在代码中凭空产生。
代码如下:
public class SSAction: ScriptableObject{
public bool enable=true; //是否存在
public bool destory=false; //是否删除
public GameObject gameobject; //动作对象
public Transform transform; //动作对象的transform
public ISSActionCallback callback; //回调函数
/*防止用户自己new对象*/
protected SSAction(){ }
public virtual void Start() {
throw new System.NotImplementedException();
}
public virtual void Update() {
throw new System.NotImplementedException();
}
}
- 实现移动功能子类SSMoveToAction:
SSMoveToAction继承自SSAction,用于把物体移动到特定地点的操作。
对象的创建由Unity负责。
移动操作在Update函数中实现。
public class SSMoveToAction: SSAction{
public Vector3 target; //目的地
public float speed; //移动速率
private SSMoveToAction(){ }
public static SSMoveToAction GetSSAction(Vector3 _target, float _speed) {
//unity创建
}
public override void Start() {
//重写
}
public override void Update() {
//实现移动动作
}
}
- 实现动作组合类SequenceAction:
实现船的移动可以很平滑,但是角色的移动需要先平移再下移。
因此要用两个动作组合成角色的移动,所以引入动作组合类。
通过动作组合类能够实现很多非常复杂的组合动作。
通过聚合容器对象来实现多个动作的保存。
这个类需要实现接口函数,方便动作之间的调度。
public class SequenceAction: SSAction,ISSActionCallback{
public List<SSAction> sequence; //动作列表
public int repeat = -1; //-1就是无限循环做组合中的动作
public int start = 0; //当前做的动作
public static SequenceAction GetSSAcition(int repeat, int start, List<SSAction> sequence) {
//unity创建
}
public override void Start() {
//执行每个动作
}
public override void Update() {
//调用动作的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.destory = false;
this.start++; //下一个动作
if (this.start >= sequence.Count) {
this.start = 0;
if (repeat > 0) repeat--;
if (repeat == 0) { //动作组合结束
this.destory = true;
this.callback.SSActionEvent(this);
}
}
}
}
- 实现动作管理类SSActionManager:
动作管理类需要存储所有的要被处理的动作,和已经处理过的动作,然后删去处理过的动作。
代码如下:
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() {
//更新链表中的动作
//删去已经处理过的
}
//执行动作
public void RunAction(GameObject gameobject, SSAction action,
ISSActionCallback manager) {
action.gameobject = gameobject;
action.transform = gameobject.transform;
action.callback = manager;
waitingAdd.Add(action);
action.Start();
}
}
- 实现本游戏的动作管理类ActionManager:
本游戏的动作管理类需要实现船移动和角色移动。
船移动一个动作;
角色移动两个动作(假如没有这个角色移动,那么完全不需要动作链表!!)。
代码如下:
public class ActionManager : SSActionManager {
public FirstController sceneController;
private SequenceAction boatMove;
private SequenceAction roleMove;
protected void Start() {
sceneController = (FirstController)SSDirect.getInstance().CurrentSceneController;
sceneController.actionManager = this;
}
protected new void Update() {
base.Update(); //直接用基类的
}
public void moveBoat(GameObject boat, Vector3 endPos, float speed) {
SSAction action1 = SSMoveToAction.GetSSAction(endPos, speed);
boatMove = SequenceAction.GetSSAcition(0, 0, new List<SSAction> { action1 });
this.RunAction(boat, boatMove, this);
}
public void moveRole(GameObject role, Vector3 middlePos, Vector3 endPos, float speed) {
//两段移动
SSAction action1 = SSMoveToAction.GetSSAction(middlePos, speed);
SSAction action2 = SSMoveToAction.GetSSAction(endPos, speed);
//两个动作
roleMove = SequenceAction.GetSSAcition(1, 0, new List<SSAction> { action1, action2 });
this.RunAction(role, roleMove, this);
}
}
至此完成了练习内容。
详细代码见gitee。