游戏对象与图形基础
1. 下载Fantasy Skybox FREE,构建自己的游戏场景
1.1 到商店选择资源 Fantasy Skybox,下载并导入。
1.2 通过步骤Gameobject–>3D Object–>Terrian添加地形并设置合适的大小
1.3 复制相同的三块
1.4 选中地形,右侧会出现Terrain -->paint Texture,熟悉各个工具的使用
1.5 在paint Texture下,Raise or lower Terrain为升高或降低地形,Paint Texture可以设置地形的图层
1.6 选择Paint Texture,单击下图位置可以将地形资源包的素材导入到设置图层的工具中,并可以构建出相同的地形。
1.7 到商店导入标准资源包Standard Assets 的Characters、CrossPlatformInput、Utility三个包,修改少量错误。
1.8 场景中导入第三人称角色
2.写一个简单总结,总结游戏对象的使用
2.1 什么是游戏对象
游戏对象 (GameObjects) 是一种容器。在里面装了个必要的Transform组件,然后还可以装其它任意的组件,这些组件共同来完成GameObject的行为。游戏对象由它拥有的组件决定功能。
2.2 如何构建游戏对象
通过可视化编辑器直接添加一个游戏对象
利用脚本构建(函数GameObject.CreatPrimitive())
通过克隆创建一个具有相同属性的游戏对象,克隆的对象彼此之间属于独立的游戏个体,不会因为克隆对象的属性的改变而改变。
通过预制(Prefabs)创建具有相同属性的游戏对象,预制对象会随着目标对象的改变而改变。
3. 牧师与魔鬼 动作分离版
3.1设计动作管理器
用一组简单的动作组合为复杂的动作。
通过门面CCActionManager输出组合好的几个动作,供原程序调用
根据所有动作的共性设计一个抽象基类SSAction
用户设计基本动作类CCMoveAction,包含游戏对象的所有基本动作
用户设计组合动作类CCSequenceAction,实现基本动作的组合
接口回调函数ISSCallBack监听子动作的事件。
通过模板类SSActionManager减少使用者对动作实现的细节的关注。
3.2 优点
使得程序更加适应需求的变化
对象更容易被复用
程序更易于维护
3.2 具体实现过程
新建Action类
动作基类:
//动作基类,实现接口通信
public class SSAction : ScriptableObject
{
public bool enable = true;
public bool destroy = false;
public GameObject gameobject;
public Transform transform;
public ISSActionCallback callback;
protected SSAction() {}
public virtual void Start()
{
throw new System.NotImplementedException();
}
public virtual void Update()
{
throw new System.NotImplementedException();
}
}
基类是动作管理器的基本元素,作为一个抽象类无需绑定GameObject,enable、destroy分别代表动作是否进行,动作是否销毁,ISSActionCallback、callback通过接口实现与游戏的通信。
利用Virtual实现多态,继承者可以使用Start和Update实现游戏对象的具体行为
简单动作实现:
//实现单个对象的动作,动作完成时销毁该动作
public class SSMoveToAction : SSAction
{
public Vector3 target;
public float speed;
private SSMoveToAction(){}
public static SSMoveToAction GetSSAction(Vector3 target, float speed)
{
SSMoveToAction action = ScriptableObject.CreateInstance<SSMoveToAction>();
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 SequenceAction: SSAction, ISSActionCallback
{
public List<SSAction> sequence;
public int repeat = -1;
public int start = 0;
public static SequenceAction GetSSAcition(int repeat, int start, List<SSAction> sequence)
{
SequenceAction action = ScriptableObject.CreateInstance<SequenceAction>();
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()
{
}
}
按照顺序播放所有动作,
- 创建一个动作顺序执行序列,-1 表示无限循环,start 开始动作。
Update
方法执行执行当前动作SSActionEvent
收到当前动作执行完成,推下一个动作,如果完成一次循环,减次数。如完成,通知该动作的管理者Start
执行动作前,为每个动作注入当前动作游戏对象,并将自己作为动作事件的接收者OnDestory
如果自己被注销,应该释放自己管理的动作。
动作时间接口定义:
//动作事件的接口
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);
DestroyObject(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();
}
public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Competeted,
int intParam = 0, string strParam = null, Object objectParam = null)
{
}
}
}
当动作做完自动回收,在这之中必然有需要等待的动作和已经做完的动作,显然,需要等待的动作加入等待列表,需要删除的动作加入删除列表。RunAction方法将游戏对象与动作进行绑定,并绑定事件的消息接收者。
实际管理类:
新建Script文件MysceneActionManager游戏对象的管理动作
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Com.Engine;
public class MySceneActionManager:SSActionManager
{
private SSMoveToAction move_boat;
private SequenceAction move_role;
public MySceneController sceneController;
protected new void Start()
{
sceneController = (MySceneController)Director.get_Instance().curren;
sceneController.actionManager = this;
}
//船的动作组合
public void moveBoat(GameObject boat, Vector3 target, float speed)
{
move_boat = SSMoveToAction.GetSSAction(target, speed);
this.RunAction(boat, move_boat, this);
}
//牧师与魔鬼的动作组合
public void moveRole(GameObject role, Vector3 middle_pos, Vector3 end_pos,float speed)
{
SSAction action1 = SSMoveToAction.GetSSAction(middle_pos, speed);
SSAction action2 = SSMoveToAction.GetSSAction(end_pos, speed);
move_role = SequenceAction.GetSSAcition(1, 0, new List<SSAction>{action1, action2});
this.RunAction(role, move_role, this);
}
}
删除之前的moveable类,使用新的动作分离方法实现游戏对象的运动。
效果展示:
操作演示
完整代码gitee地址:gitee