游戏对象与图形基础

游戏对象与图形基础

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值