本文主要是介绍3D游戏设计第五次作业,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
3D游戏设计第五次作业——打飞碟
1代码架构
本次打飞碟游戏的代码架构是根据这几次课件构建的,主要涉及是mvc架构,动作管理器和工厂模式,代码文件如下:
UML图如下:
2 代码文件
2.1单实例类Singleton.cs
在整个项目中,有些类仅需要一个实例,如飞碟工厂、动作管理器、用户GUI,通过单实例类就可以实现获取这些实例。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Singleton<T>: MonoBehaviour where T:MonoBehaviour{protected static T instance;public static T Instance{get{if(instance==null){instance = (T)FindObjectOfType(typeof(T));if(instance == null){Debug.LogError("An instance of "+typeof(T) + " is needed in the scene,but there is none.");}}return instance;}}
}
2.2 飞碟属性disk.cs
飞碟的大小、颜色、速度、运动方向各不相同,将这些属性都写在disk类中,之后作为飞碟的组件。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class disk :MonoBehaviour
{// 颜色下标0-2public int color;// 大小下标0-2public int size;// 速度下标0-2public int speed;// 运动方向public Vector3 dir;// 初始位置public Vector3 pos;
}
2.3飞碟工厂DiskFactory.cs
飞碟工厂完成获取飞碟和释放飞碟的功能,在Start方法中首先进行获取飞碟预制,然后再之后根据需要实例化。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DiskFactory : MonoBehaviour
{private List<disk> free = new List<disk>();private List<disk> used = new List<disk>();Color[] colors =new Color[3] {Color.cyan,Color.gray,Color.red};float []sizes = new float[3]{1.5F,1.0F,0.5F};GameObject pre;public GameObject getDisk(){GameObject obj;if(free.Count>0){obj = free[0].gameObject;free.RemoveAt(0);}else{obj = Instantiate(pre);obj.AddComponent<disk>();}// 颜色obj.GetComponent<disk>().color = Random.Range(0,3);obj.GetComponent<MeshRenderer>().material.color = colors[obj.GetComponent<disk>().color];//大小obj.GetComponent<disk>().size = Random.Range(0,3);int t = obj.GetComponent<disk>().size;obj.transform.localScale = new Vector3(sizes[t],sizes[t],sizes[t]);//速度obj.GetComponent<disk>().speed = Random.Range(1,4);//方向obj.GetComponent<disk>().dir = new Vector3(Random.Range(2,4),Random.Range(0,2),0);//初始位置obj.GetComponent<disk>().pos = new Vector3(-6,0,0);obj.transform.position = obj.GetComponent<disk>().pos;used.Add(obj.GetComponent<disk>());return obj;}// Start is called before the first frame updatevoid Start(){pre = (GameObject)Resources.Load("prefabs/hitdisk/disk");}public void FreeDisk(disk dis){Debug.Log("factory free");foreach(disk d in used){if(d.gameObject.GetInstanceID()==dis.gameObject.GetInstanceID()){Debug.Log("find and free");free.Add(dis);used.Remove(dis);return;}}}
}
2.4动作基类SSSAction.cs
动作基类是后来实现飞行动作的父类,提供动作基类便于后续类调用动作类的方法。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SSSAction :ScriptableObject
{public bool enable = true;public bool destroy = false;public GameObject gameObject{get;set;}public Transform transform{get;set;}public IISSActionCallback callback{get;set;}protected SSSAction(){}// Start is called before the first frame updatepublic virtual void Start(){}// Update is called once per framepublic virtual void Update(){}
}
2.5 飞行动作类CCFlyAction.cs
飞行动作类在Update方法中实现物体的移动,这里我将飞行行动设置为简单的匀速直线运动。当飞碟飞出屏幕或被点击时,即会调用回调函数通知动作管理器。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CCFlyAction : SSSAction
{public float speed;public Vector3 direction;public static CCFlyAction GetSSAction(Vector3 direction, float speed ){CCFlyAction action = ScriptableObject.CreateInstance<CCFlyAction>();action.speed = speed;action.direction = direction;return action;}// Start is called before the first frame updatepublic override void Start(){}// Update is called once per framepublic override void Update(){if(this.enable==true){this.gameObject.transform.position += direction*speed*Time.deltaTime;if(this.gameObject.transform.position.y>5||this.gameObject.transform.position.y<-5||this.gameObject.transform.position.x>9){this.destroy = true;this.enable = false;this.callback.SSSActionEvent(this);}}}
}
2.6 动作管理器基类SSActionManager.cs
使用RunAction方法为飞碟添加动作,并且开始动作。在Update中根据动作的状态进行相应的操作,destroy为真则将其添加在删除队列,enable为真则进行该动作。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SSActionManager : MonoBehaviour
{private Dictionary<int,SSSAction> actions = new Dictionary<int,SSSAction>();private List<SSSAction> waitingAdd = new List<SSSAction>();private List<int> waitingDelete = new List<int>();// Start is called before the first frame updatevoid Start(){}// Update is called once per frameprotected void Update(){foreach(SSSAction ac in waitingAdd) actions[ac.GetInstanceID()] = ac;waitingAdd.Clear();foreach(KeyValuePair<int,SSSAction>kv in actions){SSSAction ac = kv.Value;if(ac.destroy){waitingDelete.Add(ac.GetInstanceID());}else if(ac.enable){ac.Update();}}foreach(int key in waitingDelete){SSSAction ac = actions[key];actions.Remove(key);Destroy(ac);}waitingDelete.Clear();}public void RunAction(GameObject gameobject,SSSAction action, IISSActionCallback manager){action.gameObject = gameobject;action.transform = gameobject.transform;action.callback = manager;waitingAdd.Add(action);action.Start();}
}
2.7飞行动作管理器CCActionManager.cs
方法SSActionEvent在接收到动作回调时,通知场景控制器释放飞碟。方法Fly提供给场景控制器,使得场景控制器可以控制飞碟开始进行飞行动作。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CCActionManager : SSActionManager, IISSActionCallback
{public DiskSceneController sceneController;public CCFlyAction fly;// Start is called before the first frame updateprotected void Start(){sceneController = (DiskSceneController)SSSDirector.getInstance().currentSceneController;sceneController.actionManager = this;}public void Fly(GameObject disk, float speed, Vector3 dir){fly = CCFlyAction.GetSSAction(dir,speed);RunAction(disk, fly, this);}// Update is called once per frameprotected new void Update(){base.Update();}#region IISSActionCallback implementationpublic void SSSActionEvent(SSSAction source, SSActionEventType events = SSActionEventType.Completed,int intParam = 0,string strParam = null, Object objectParam = null){// Debug.Log("manager free");sceneController.FreeDisk(source.gameObject);}#endregion
}
2.8 动作回调接口IISSActionCallback.cs
该接口实现了SSSActionEvent方法,是用于动作管理器在动作完成时接收到动作完成的消息,从而进行相应释放物体操作。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum SSActionEventType:int{Started, Completed}
public interface IISSActionCallback{void SSSActionEvent(SSSAction source,SSActionEventType events = SSActionEventType.Completed,int intParam = 0,string strParam = null,Object objectParam = null);
}
2.9 用户动作接口IIUserAction.cs
该接口提供了用户交互会涉及到的几个方法。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public interface IIUserAction{GameState getGS();void GameOver();void gameStart();void Hit(Vector3 pos);
}
2.10 用户交互类UUserGUI.cs
用户交互类响应用户鼠标的点击动作,当点击物体时调用场景控制器的Hit方法,当点击开始按钮时即开始游戏。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum GameState{ running,start,end,beforeStart}public class UUserGUI : MonoBehaviour
{int score=0;private IIUserAction action;// Start is called before the first frame updatevoid Start(){ Debug.Log("action init");action = SSSDirector.getInstance().currentSceneController as IIUserAction;Debug.Log("action name"+action.ToString());}public void setScore(int s){score = s;}// Update is called once per framevoid OnGUI(){GUI.Label(new Rect(10,10,100,50),"得分:"+score);// if(action.getGS() != GameState.running){if(action.getGS()!=GameState.running){if(GUI.Button(new Rect(100,150,100,50),"开始")){action.gameStart();}}if(Input.GetMouseButtonDown(0)){action.Hit(Input.mousePosition);}if(action.getGS()==GameState.end){GUI.Label(new Rect(Screen.width/2-50,Screen.height/2-25,100,50),"游戏结束!");}// }}
}
2.11 场景控制器接口IISceneController.cs
场景控制器接口提供一个场景控制器应该实现的几个方法。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public interface IISceneController{void LoadResources();void Pause();void Resume();
}
2.12 飞碟场景控制器DiskSceneController.cs
场景控制器实现游戏的逻辑,完成丢飞盘、获取游戏状态、释放飞盘、重新开始游戏等的方法。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DiskSceneController : MonoBehaviour, IISceneController, IIUserAction
{float time = 0;int throwCount = 0;public int disknum = 10;public GameState state = GameState.beforeStart;int score = 0;DiskFactory diskfactory;public CCActionManager actionManager;UUserGUI usergui;//要移动的物体public GameObject obj;// Start is called before the first frame updatevoid Start(){SSSDirector director = SSSDirector.getInstance();director.currentSceneController = this;gameObject.AddComponent<DiskFactory>();gameObject.AddComponent<CCActionManager>();gameObject.AddComponent<UUserGUI>();LoadResources();}public void LoadResources(){diskfactory = Singleton<DiskFactory>.Instance;usergui = Singleton<UUserGUI>.Instance;actionManager = Singleton<CCActionManager>.Instance;}public void Hit(Vector3 pos){Ray ray = Camera.main.ScreenPointToRay(pos);RaycastHit hit;bool isCollider = Physics.Raycast(ray, out hit);if(isCollider){var fa = hit.collider.gameObject.transform.parent;fa.position = new Vector3(0,-6,0);score += countScore(fa.gameObject.GetComponent<disk>());usergui.setScore(score);}}public GameState getGS(){return state;}private int countScore(disk d){return d.color + d.size +4- d.speed;}public void Pause(){}public void Resume(){throwCount = 0;time = 0;score = 0;usergui.setScore(0);}void Update(){if(state==GameState.running){if(throwCount>=20){state = GameState.end;}time += Time.deltaTime;if(time>0.5){time = 0;for(int i = 0;i<3;i++){throwCount++;ThrowDisk();}}}}public void ThrowDisk(){GameObject disk = diskfactory.getDisk();actionManager.Fly(disk, disk.GetComponent<disk>().speed,disk.GetComponent<disk>().dir);}public void gameStart(){Resume();state = GameState.running;}public void FreeDisk(GameObject disk){Debug.Log("scene free"); diskfactory.FreeDisk(disk.GetComponent<disk>());}public void GameOver(){}
}
2.13导演类SSSDirector.cs
getInstance方法获得当前的场景控制器,_instance是静态成员变量,因此总是只有一个场景控制器。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SSSDirector : System.Object
{private static SSSDirector _instance;public IISceneController currentSceneController{get;set;}public bool running{get;set;}public static SSSDirector getInstance(){if(_instance == null){_instance = new SSSDirector();}return _instance;}}
3 视频展示和代码链接
视频链接:https://www.bilibili.com/video/BV1rP4y117Sx/?vd_source=aa1381bc757a530f161653f21b4b7d29
代码链接:https://gitee.com/k_co/3-d-games/tree/master/HW5
提交的代码去掉了天空盒。
这篇关于3D游戏设计第五次作业的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!