背景:
距离公司新项目《赶海王》上线也有一个多月了,这么多年写过mmorpg类,动作类,卡牌类,小游戏还是头一遭。你可以什么都不服,但是时间总会把你制的服服贴贴。为了这次项目经历还能剩下点东西,我决定还是用文字记录一下还能想起的东西吧。
一如上线游戏中的赶海玩法,捕鱼的过程是可以拆解出一个个顺序的节点(你说鱼可能同时旋转加位移,我们可以当作是一个复杂节点),我们把这种顺序式称为Flow式,下面我们把整个思路整理一下。以下伪代码和截图只包含具体思路,并不包含逻辑细节。
参与对象:
Player类,Fish类,Pincer类等
附上基类结构,特殊类可以根据需求完成。
public abstract class Object
{
public int EntityID { private set; get; }
public GameWorldBase World { private set; get; }
public GameObject Root { private set; get; }
public Entity Avatar { private set; get; }
public Vector2 Grid { private set; get; }
public Object(int entityID)
{
EntityID = entityID;
}
public void Create(GameWorldBase world, int avatarID, Vector3 pos, Vector3 rot)
{
}
public void Destroy()
{
}
public void Update(float deltaTime)
{
}
public void HandleEvent(Message msg)
{
}
protected virtual void OnCreate() { }
protected virtual void OnDestroy() { }
protected virtual void OnUpdate(float deltaTime) { }
protected virtual void OnHandleEvent(Message msg) { }
}
动作节点:
节点的基础类ActionNode:
public abstract class ActionNode
{
private ActionDirector director;
protected Player player;
protected Fish pickItem;
protected bool isAction = false;
protected bool isPause = false;
public int ActionType;
public ActionNode(ActionDirector director)
{
this.director = director;
player = director.GetPlayer();
pickItem = director.GetPickup();
}
public virtual void OnEnter()
{
isAction = true;
}
public virtual bool OnUpdate(float dt)
{
if (!isAction)
return false;
if (isPause)
return false;
return true;
}
public virtual void OnPause()
{
isPause = true;
}
public virtual void OnResume()
{
isPause = false;
}
public virtual void OnExit()
{
isAction = false;
}
public bool CanDoNext
{
get { return !isAction && !isPause; }
}
}
特殊节点类:
ActionParallel:平行节点,包含多个子节点,子节点同时运行
ActionSequence:顺序节点,包含多个子节点,子节点按顺序执行
ActionCondition:选择节点,包含两个子节点,根据输入执行对应节点
其他节点:
ActionDelay延迟节点,ActionAudio声音节点等其他各种各样的功能节点,根据功能不断扩充。
导演:
ActionDirector导演类,主要记录所有的Node节点,和节点的顺序执行。同时还包含节点数据的解析(根据编辑器存储的数据实例化出对应的各种节点)
public class ActionDirector
{
private Player player;
private Fish pickItem;
private bool isPerforming = false;
private List<ActionNode> actionNodes = new List<ActionNode>();
private ActionNode actionNode = null;
public ActionDirector()
{
}
public void OnUpdate(float dt)
{
}
public void OnDestory()
{
}
public static ActionNode ParseAction(SimpleDirector director, ActionDataNode data)
{
return null;
}
}
节点编辑器:
根据不同节点的数据类型显示在编辑中显示出来:如
private void _GUIFieldCurve(ActionDataNode actionNode, SerializedProperty sp, string labelText=null)
{
actionNode.Curve = sp.FindPropertyRelative("Curve").animationCurveValue;
actionNode.Curve = EditorGUILayout.CurveField(string.IsNullOrEmpty(labelText)?"Curve":labelText, actionNode.Curve);
}
最终的实现效果如下:

文章评论