Unity:游戏对象与图形基础

编程入门 行业动态 更新时间:2024-10-20 03:24:56

Unity:游戏对象与<a href=https://www.elefans.com/category/jswz/34/1770818.html style=图形基础"/>

Unity:游戏对象与图形基础

游戏对象与图形基础-作业与练习

github地址


1、基本操作演练

  • 下载天空和skybox, 构建自己的游戏场景

    从Asset Store下载skybox然后导入

  • 制作天空盒

    • 在Assets中右击->Create->Material
    • 将shader改为Skybox/6 sided并把对应的图片放进去

  • 创建地图
    • 在对象栏右击->3D Object->Terrain,新建一个地图对象

    • 使用Terrain的各项工具绘制地图, 包括造山,造草,添加细节等等

    • 先画地形

  • 种草种树


(好丑) 镜头拉远会看不到草跟树

游戏对象使用总结:

  • 目前学过的有基础掌握的对象主要有:
    • Camera:
      通过Camera来观察游戏世界,看到Camera里投影。
    • Light:
      光源,可以用来照明也可用于添加阴影等效果。
    • Empty:
      空对象多被用于当做载体,例如挂载游戏脚本、成为其他对象的父对象等。
    • Cube、sphere、Capsule等3D Object:
      搭建游戏世界的组成元素,通过设置其Transform等属性来变换它们的位置、形态等。
    • Terrain等:
      Terrain本身是地图,然后又附带了绘制地图的各项工具(造山、造草等)。

编程实践: 牧师与魔鬼分离版

  • 【2019新要求】:设计一个裁判类,当游戏达到结束条件时,通知场景控制器游戏结束

    结构:

  1. 先把Judge裁判类设计好,其实就是把先前检查游戏结束条件的方法抽出来构成一个类而已,FirstController类调用CheckGameState()方法查看游戏是否结束(0为正在进行,1为失败,2为获胜)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Judge : MonoBehaviour
{public CoastController startCoast;      //右岸public CoastController endCoast;        //左岸public BoatController boat;             //船//实例化的同时同步对象public Judge(CoastController start, CoastController end, BoatController b){startCoast = start;endCoast = end;boat = b;}// 检查游戏是否结束public int CheckGameState(){int start_priest = (startCoast.GetobjectsNumber())[0];int start_devil = (startCoast.GetobjectsNumber())[1];int end_priest = (endCoast.GetobjectsNumber())[0];int end_devil = (endCoast.GetobjectsNumber())[1];if (end_priest == 3 && end_devil == 3)return 2;int[] boat_roles = boat.GetobjectsNumber();//船在开始岸if (boat.get_State() == 1){start_priest += boat_roles[0];start_devil += boat_roles[1];}else //穿在结束岸{end_priest += boat_roles[0];end_devil += boat_roles[1];}if ((start_priest > 0 && start_priest < start_devil) || (end_priest > 0 && end_priest < end_devil))return 1;return 0;}
}
  1. SSAction类:SSAction是所有动作的基类,ScriptableObject 是不需要绑定 GameObject 对象的可编程基类。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Interfaces;//动作分离
public class SSAction : ScriptableObject {public bool enable = true;public bool destroy = false;public GameObject gameObject;       //动作发出的对象public Transform transform;         //对象的transformpublic SSActionCallback CallBack;   //回调函数public virtual void Start(){throw new System.NotImplementedException();}public virtual void Update(){throw new System.NotImplementedException();}
}//移动动作,继承SSAction
public class CCMoveToAction : SSAction
{public Vector3 target;         //终点public float speed;            //速度private CCMoveToAction() { }//静态函数public static CCMoveToAction getAction(Vector3 target, float speed){//单例模式CCMoveToAction action = ScriptableObject.CreateInstance<CCMoveToAction>();action.target = target;action.speed = speed;return action;}//重写Update函数public override void Update(){//移动this.transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);//到达目的地设置destroy为true,销毁这个动作,回调if (transform.position == target){destroy = true;CallBack.SSActionCallback(this);}}public override void Start(){}
}//动作列表
public class CCSequenceAction : SSAction, SSActionCallback
{public List<SSAction> sequence;         //存储一连续的动作public int repeat = 1;                  // 1->only do it for once, -1->repeat foreverpublic int currentActionIndex = 0;      //当前轮到的动作下标//获取动作public static CCSequenceAction getAction(int repeat, int currentActionIndex, List<SSAction> sequence){CCSequenceAction action = ScriptableObject.CreateInstance<CCSequenceAction>();action.sequence = sequence;action.repeat = repeat;action.currentActionIndex = currentActionIndex;return action;}//重写Updatepublic override void Update(){if (sequence.Count == 0) return;if (currentActionIndex < sequence.Count){sequence[currentActionIndex].Update();//调用sequence里当前的做的Update方法}}//接口要求重写的函数,传入一个动作进行回调public void SSActionCallback(SSAction source){source.destroy = false;this.currentActionIndex++; //轮到下一个动作if (this.currentActionIndex >= sequence.Count)  //超过范围{this.currentActionIndex = 0;if (repeat > 0) repeat--;if (repeat == 0){this.destroy = true;this.CallBack.SSActionCallback(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(){foreach (SSAction action in sequence){Destroy(action);        //销毁对象(动作)}}
}//动作管理器
public class SSActionManager : MonoBehaviour
{private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();        //正在进行private List<SSAction> waitingToAdd = new List<SSAction>();                         //等待添加private List<int> watingToDelete = new List<int>();                                 //等待销毁protected void Update(){//等待队列里的动作都添加到actionsforeach (SSAction ac in waitingToAdd){actions[ac.GetInstanceID()] = ac;}waitingToAdd.Clear();//获取每一个动作,检查是否完成foreach (KeyValuePair<int, SSAction> kv in actions){SSAction ac = kv.Value;//动作的destroy属性为true是加入到销毁对列里if (ac.destroy){watingToDelete.Add(ac.GetInstanceID());}else if (ac.enable) {ac.Update();}}//对销毁队列的每一个动作foreach (int key in watingToDelete){SSAction ac = actions[key];actions.Remove(key);Destroy(ac);}watingToDelete.Clear();}//添加动作,传入对象,动作,和回调函数public void addAction(GameObject gameObject, SSAction action, SSActionCallback ICallBack){action.gameObject = gameObject;action.transform = gameObject.transform;action.CallBack = ICallBack;waitingToAdd.Add(action);action.Start();}
}

  1. CCMoveToAction类(SSACtion.cs里):实现简单的动作,并且管理内存回收以及重写Update()函数实现物体的运动。
//移动动作,继承SSAction
public class CCMoveToAction : SSAction
{public Vector3 target;         //终点public float speed;            //速度private CCMoveToAction() { }//静态函数public static CCMoveToAction getAction(Vector3 target, float speed){//单例模式CCMoveToAction action = ScriptableObject.CreateInstance<CCMoveToAction>();action.target = target;action.speed = speed;return action;}//重写Update函数public override void Update(){//移动this.transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);//到达目的地设置destroy为true,销毁这个动作,回调if (transform.position == target){destroy = true;CallBack.SSActionCallback(this);}}public override void Start(){}
}

  1. CCSequenceAction类(SSAction.cs里):创建动作执行序列,按要求循环执行保存的动作序列。
//动作列表
public class CCSequenceAction : SSAction, SSActionCallback
{public List<SSAction> sequence;         //存储一连续的动作public int repeat = 1;                  // 1->only do it for once, -1->repeat foreverpublic int currentActionIndex = 0;      //当前轮到的动作下标//获取动作public static CCSequenceAction getAction(int repeat, int currentActionIndex, List<SSAction> sequence){CCSequenceAction action = ScriptableObject.CreateInstance<CCSequenceAction>();action.sequence = sequence;action.repeat = repeat;action.currentActionIndex = currentActionIndex;return action;}//重写Updatepublic override void Update(){if (sequence.Count == 0) return;if (currentActionIndex < sequence.Count){sequence[currentActionIndex].Update();//调用sequence里当前的做的Update方法}}//接口要求重写的函数,传入一个动作进行回调public void SSActionCallback(SSAction source){source.destroy = false;this.currentActionIndex++; //轮到下一个动作if (this.currentActionIndex >= sequence.Count)  //超过范围{this.currentActionIndex = 0;if (repeat > 0) repeat--;if (repeat == 0){this.destroy = true;this.CallBack.SSActionCallback(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(){foreach (SSAction action in sequence){Destroy(action);        //销毁对象(动作)}}
}

  1. SSActionCallback接口:定义了事件处理接口,所有事件管理者都必须实现这个接口来实现事件调度。
public interface SSActionCallback
{void SSActionCallback(SSAction source);
}

  1. SSActionManager类(SSAction.cs里):动作管理的基类,使用上述的移动方法,实现游戏对象与动作的绑定,确定回调函数消息的接收对象。
//动作管理器
public class SSActionManager : MonoBehaviour
{private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();        //正在进行private List<SSAction> waitingToAdd = new List<SSAction>();                         //等待添加private List<int> watingToDelete = new List<int>();                                 //等待销毁protected void Update(){//等待队列里的动作都添加到actionsforeach (SSAction ac in waitingToAdd){actions[ac.GetInstanceID()] = ac;}waitingToAdd.Clear();//获取每一个动作,检查是否完成foreach (KeyValuePair<int, SSAction> kv in actions){SSAction ac = kv.Value;//动作的destroy属性为true是加入到销毁对列里if (ac.destroy){watingToDelete.Add(ac.GetInstanceID());}else if (ac.enable) {ac.Update();}}//对销毁队列的每一个动作foreach (int key in watingToDelete){SSAction ac = actions[key];actions.Remove(key);Destroy(ac);}watingToDelete.Clear();}//添加动作,传入对象,动作,和回调函数public void addAction(GameObject gameObject, SSAction action, SSActionCallback ICallBack){action.gameObject = gameObject;action.transform = gameObject.transform;action.CallBack = ICallBack;waitingToAdd.Add(action);action.Start();}
}
  1. FirstSceneActionManager类:当前场景下的动作管理的具体实现,与场景控制基类配合,实现对当前场景的直接管理。挂载到图像中的Main空对象上实现对预制加载的场景的管理。
//挂到空项目上,继承动作管理器和回调接口
public class FirstSceneActionManager : SSActionManager, SSActionCallback
{public SSActionEventType Complete = SSActionEventType.Completed;    //事件的状态是否完成//船移动public void BoatMove(BoatController Boat){Complete = SSActionEventType.Started;CCMoveToAction action = CCMoveToAction.getAction(Boat.GetDestination(), Boat.GetMoveSpeed());addAction(Boat.GetGameObject(), action, this);  //见SSAcitonManagerBoat.ChangeState(); //改变船的状态}//人物对象移动public void GameObjectsMove(GameObjects GameObject, Vector3 Destination){Complete = SSActionEventType.Started;//防止撞墙,定义一个中点坐标Vector3 CurrentPos = GameObject.GetPosition();Vector3 MiddlePos = CurrentPos;if (Destination.y > CurrentPos.y){MiddlePos.y = Destination.y;}else{MiddlePos.x = Destination.x;}//先移动到中间SSAction action1 = CCMoveToAction.getAction(MiddlePos, GameObject.GetMoveSpeed());//在移动到目的地SSAction action2 = CCMoveToAction.getAction(Destination, GameObject.GetMoveSpeed());//CCSequenceAction是SSAction的子类SSAction seqAction = CCSequenceAction.getAction(1, 0, new List<SSAction> { action1, action2 });//这个类继承了SSActionManager,管理动作this.addAction(GameObject.GetGameobject(), seqAction, this);}//回调函数SSActionEventType设置为Completedpublic void SSActionCallback(SSAction source){Complete = SSActionEventType.Completed;}
}
  1. FirstController类(挂到空项目上的cs文件):实现使用动作分离的动作管理:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Interfaces;//挂在空项目上
public class FirstController : MonoBehaviour, ISceneController, UserAction
{InteracteGUI UserGUI;       //玩家GUIpublic CoastController fromCoast;   //右岸public CoastController toCoast;     //左岸public BoatController boat;         //船private GameObjects[] GameObjects;  //人物public Judge judge;     //裁判类private FirstSceneActionManager FCActionManager;    //动作场景控制器void Start(){FCActionManager = GetComponent<FirstSceneActionManager>();  //初始化judge = new Judge(fromCoast, toCoast, boat); //初始化裁判类}void Awake()    //唤醒,各类的初始化{SSDirector director = SSDirector.getInstance();director.currentScenceController = this;UserGUI = gameObject.AddComponent<InteracteGUI>() as InteracteGUI;GameObjects = new GameObjects[6];LoadResources();}public void LoadResources()  //ISceneController接口实现的方法,实例化各对象{fromCoast = new CoastController("from");toCoast = new CoastController("to");boat = new BoatController();GameObject water = Instantiate(Resources.Load("Perfabs/Water", typeof(GameObject)), new Vector3(0, 0.5F, 0), Quaternion.identity, null) as GameObject;water.name = "water";for (int i = 0; i < 3; i++){GameObjects s = new GameObjects("priest");s.setName("priest" + i);s.setPosition(fromCoast.getEmptyPosition());s.getOnCoast(fromCoast);fromCoast.getOnCoast(s);GameObjects[i] = s;}for (int i = 0; i < 3; i++){GameObjects s = new GameObjects("devil");s.setName("devil" + i);s.setPosition(fromCoast.getEmptyPosition());s.getOnCoast(fromCoast);fromCoast.getOnCoast(s);GameObjects[i + 3] = s;}}public void ObjectIsClicked(GameObjects Objects)    //人物被点击事件{if (FCActionManager.Complete == SSActionEventType.Started) return;if (Objects.isOnBoat())         //对象在船上{CoastController whichCoast;if (boat.get_State() == -1){ // to->-1; from->1whichCoast = toCoast;}else{whichCoast = fromCoast;}boat.GetOffBoat(Objects.getName()); //下船,操作船对象FCActionManager.GameObjectsMove(Objects,whichCoast.getEmptyPosition()); //移动到空位置Objects.getOnCoast(whichCoast); //登陆,操作人物对象whichCoast.getOnCoast(Objects); //登陆,操作岸对象}else  //对象在岸上{Debug.Log("On Coast!");CoastController whichCoast = Objects.getCoastController(); // obejects on coastif (boat.getEmptyIndex() == -1){      return;}if (whichCoast.get_State() != boat.get_State())   // boat is not on the side of characterreturn;whichCoast.getOffCoast(Objects.getName());          //下岸,操作岸对象FCActionManager.GameObjectsMove(Objects, boat.getEmptyPosition());      //移动Objects.getOnBoat(boat);    //上船,操作人物对象boat.GetOnBoat(Objects);    //上船,操作船对象}// UserGUI.SetState = Check();UserGUI.SetState = judge.CheckGameState();}public void MoveBoat(){if (FCActionManager.Complete == SSActionEventType.Started || boat.isEmpty()) return;FCActionManager.BoatMove(boat);//UserGUI.SetState = Check();UserGUI.SetState = judge.CheckGameState();}//有了裁判类这个函数就不用到了int Check(){   // 0->not finish, 1->lose, 2->winint from_priest = 0;int from_devil = 0;int to_priest = 0;int to_devil = 0;int[] fromCount = fromCoast.GetobjectsNumber();from_priest += fromCount[0];from_devil += fromCount[1];int[] toCount = toCoast.GetobjectsNumber();to_priest += toCount[0];to_devil += toCount[1];if (to_priest + to_devil == 6)      // winreturn 2;int[] boatCount = boat.GetobjectsNumber();if (boat.get_State() == -1){   // boat at toCoastto_priest += boatCount[0];to_devil += boatCount[1];}else{   // boat at fromCoastfrom_priest += boatCount[0];from_devil += boatCount[1];}if (from_priest < from_devil && from_priest > 0){       // losereturn 1;}if (to_priest < to_devil && to_priest > 0){return 1;}return 0;           // not finish}//重置public void Restart(){fromCoast.reset();toCoast.reset();foreach (GameObjects gameobject in GameObjects){gameobject.reset();}boat.reset();}
}

其他函数改动不大


总结

实现动作分离,并添加裁判类,裁判类再FirstController里用到,用于检查游戏状态是否结束。

更多推荐

Unity:游戏对象与图形基础

本文发布于:2024-02-07 10:46:49,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1756160.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:图形   对象   基础   游戏   Unity

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!