简介
用 Unity实现一个简单的小游戏,就做牧师与魔鬼,没玩过的童鞋们可以去玩一玩,一个益智小游戏传送门
(之前做了个没有动作分离的。。但是那时忘了发博客。。于是。。只能做动作分离版的了)
UML图
这个框架主要参考了老师上课给的框架。。而且大部分代码都是参考老师的代码。。
对象处理
由于是做一个简单的小游戏,所以人物什么的模型也没有花心思去找了。
蓝色的矩形表示船
红色的球表示魔鬼(注意:在Tag那里也要设为魔鬼,方便代码调用)
绿色的球表示牧师(注意项跟魔鬼相同)
代码
代码。。貌似有点多
SSDirector.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum State { WIN, LOSE, PAUSE, CONTINUE , START };
public class SSDirector : System.Object {
private static SSDirector _instance;
public int totalSeconds = 60;
public int leaveSeconds;
public bool onCountDown = false;
public string countDownTitle = "Start";
public ISceneController currentSceneController { get; set; }
public State state { get; set; }
public bool running { get; set; }
// get instance anytime anywhere!
public static SSDirector getInstance() {
if (_instance == null) {
_instance = new SSDirector ();
}
return _instance;
}
public int getFPS() {
return Application.targetFrameRate;
}
public void setFPS(int fps) {
Application.targetFrameRate = fps;
}
public IEnumerator DoCountDown() {
while (leaveSeconds > 0) {
yield return new WaitForSeconds (1f);
leaveSeconds--;
}
}
}
FirstController.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FirstController : MonoBehaviour, IUserAction, ISceneController {
public CCActionManager actionManager;
List<GameObject> LeftObjList = new List<GameObject>();
List<GameObject> RightObjList = new List<GameObject>();
GameObject[] boat = new GameObject[2];
GameObject boat_obj, leftShore_obj, rightShore_obj;
Vector3 LeftShorePos = new Vector3(-12, 0, 0);
Vector3 RightShorePos = new Vector3(12, 0, 0);
Vector3 BoatLeftPos = new Vector3(-4, 0, 0);
Vector3 BoatRightPos = new Vector3(4, 0, 0);
void Awake() {
SSDirector director = SSDirector.getInstance();
director.setFPS(60);
director.currentSceneController = this;
director.currentSceneController.LoadResources();
director.leaveSeconds = director.totalSeconds;
}
void Start () {
SSDirector.getInstance().state = State.PAUSE;
SSDirector.getInstance().countDownTitle = "Start";
actionManager = GetComponent<CCActionManager>() as CCActionManager;
}
void Update() {
check();
}
public void LoadResources() {
GameObject priest_obj, devil_obj;
Camera.main.transform.position = new Vector3(0, 0, -20);
leftShore_obj = Instantiate(Resources.Load("prefabs/Shore"), LeftShorePos, Quaternion.identity) as GameObject;
rightShore_obj = Instantiate(Resources.Load("prefabs/Shore"), RightShorePos, Quaternion.identity) as GameObject;
leftShore_obj.name = "left_shore";
rightShore_obj.name = "right_shore";
boat_obj = Instantiate(Resources.Load("prefabs/Boat"), BoatLeftPos, Quaternion.identity) as GameObject;
boat_obj.name = "boat";
boat_obj.transform.parent = leftShore_obj.transform;
for (int i = 0; i < 3; ++i) {
priest_obj = Instantiate(Resources.Load("prefabs/Priest")) as GameObject;
priest_obj.name = i.ToString();
priest_obj.transform.position = new Vector3(-16f + 1.5f * Convert.ToInt32(priest_obj.name), 2.7f, 0);
priest_obj.transform.parent = leftShore_obj.transform;
LeftObjList.Add(priest_obj);
devil_obj = Instantiate(Resources.Load("prefabs/Devil")) as GameObject;
devil_obj.name = (i + 3).ToString();
devil_obj.transform.position = new Vector3(-16f + 1.5f * Convert.ToInt32(devil_obj.name), 2.7f, 0);
devil_obj.transform.parent = leftShore_obj.transform;
LeftObjList.Add(devil_obj);
}
}
public void click() {
GameObject gameObj = null;
if (Input.GetMouseButtonDown(0) &&
(SSDirector.getInstance().state == State.START || SSDirector.getInstance().state == State.CONTINUE)) {
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit)) gameObj = hit.transform.gameObject;
}
if (gameObj == null) return;
else if (gameObj.name == "0" || gameObj.name == "1" || gameObj.name == "2"
|| gameObj.name == "3" || gameObj.name == "4" || gameObj.name == "5")
MovePeople(gameObj);
else if(gameObj.name == "boat") MoveBoat();
}
void MovePeople(GameObject people) {
int shoreNum, seatNum;
if (people.transform.parent == boat_obj.transform.parent && (boat[0] == null || boat[1] == null)) {
seatNum = boat[0] == null ? 0 : 1;
if (people.transform.parent == leftShore_obj.transform) {
shoreNum = 0;
for (int i = 0; i < LeftObjList.Count; i++) {
if (people.name == LeftObjList[i].name) {
Debug.Log (actionManager);
actionManager.getOnBoat(people, shoreNum, seatNum);
LeftObjList.Remove(LeftObjList[i]);
}
}
} else {
shoreNum = 1;
for (int i = 0; i < RightObjList.Count; i++) {
if (people.name == RightObjList[i].name) {
actionManager.getOnBoat(people, shoreNum, seatNum);
RightObjList.Remove(RightObjList[i]);
}
}
}
boat[seatNum] = people;
people.transform.parent = boat_obj.transform;
} else if (people.transform.parent == boat_obj.transform) {
shoreNum = boat_obj.transform.parent == leftShore_obj.transform ? 0 : 1;
seatNum = (boat[0] != null && boat[0].name == people.name) ? 0 : 1;
actionManager.getOffBoat(people, shoreNum);
boat[seatNum] = null;
if(shoreNum == 0) {
people.transform.parent = leftShore_obj.transform;
LeftObjList.Add(people);
} else {
people.transform.parent = rightShore_obj.transform;
RightObjList.Add(people);
}
}
}
void MoveBoat() {
if (!(boat[0]==null && boat[1] == null)) {
actionManager.moveBoat(boat_obj);
boat_obj.transform.parent = boat_obj.transform.parent == leftShore_obj.transform ? rightShore_obj.transform : leftShore_obj.transform;
}
}
public void check() {
int left_d = 0, left_p = 0, right_d = 0, right_p = 0;
foreach (GameObject element in LeftObjList) {
if (element.tag == "Priest") left_p++;
if (element.tag == "Devil") left_d++;
}
foreach (GameObject element in RightObjList) {
if (element.tag == "Priest") right_p++;
if (element.tag == "Devil") right_d++;
}
for (int i = 0; i < 2; i++) {
if (boat[i] != null && boat_obj.transform.parent == leftShore_obj.transform) {
if (boat[i].tag == "Priest") left_p++;
else left_d++;
}
if (boat[i] != null && boat_obj.transform.parent == rightShore_obj.transform) {
if (boat[i].tag == "Priest") right_p++;
else right_d++;
}
}
if ((left_d > left_p && left_p != 0) || (right_d > right_p && right_p != 0) || SSDirector.getInstance().leaveSeconds == 0)
SSDirector.getInstance().state = State.LOSE;
else if (right_d == right_p && right_d == 3) SSDirector.getInstance().state = State.WIN;
}
public void Pause() {
SSDirector.getInstance().state = State.PAUSE;
}
public void Resume() {
SSDirector.getInstance().state = State.CONTINUE;
}
public void Restart() {
Application.LoadLevel(Application.loadedLevelName);
SSDirector.getInstance().state = State.START;
}
}
SSActionManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SSActionManager : MonoBehaviour {
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.destory) {
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();
}
protected void Start() {}
}
SSAction.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SSAction : ScriptableObject {
public bool enable = true;
public bool destory = false;
public GameObject gameobject{ get; set;}
public Transform transform{ get; set; }
public ISSActionCallback callback{ get; set; }
protected SSAction() {}
public virtual void Start () {
throw new System.NotImplementedException();
}
public virtual void Update () {
throw new System.NotImplementedException ();
}
}
CCMoveToAction.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CCMoveToAction : SSAction {
public Vector3 target;
public float speed;
public static CCMoveToAction GetSSAction (Vector3 target, float speed) {
CCMoveToAction action = ScriptableObject.CreateInstance<CCMoveToAction>();
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.destory = true;
this.callback.SSActionEvent (this);
}
}
public override void Start () {}
}
CCSequenceAction.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CCSequenceAction : SSAction, ISSActionCallback {
public List<SSAction> sequence;
public int repeat = -1;
public int start = 0;
public static CCSequenceAction GetSSAction (int repeat, int start, List<SSAction> sequence) {
CCSequenceAction action = ScriptableObject.CreateInstance<CCSequenceAction> ();
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.Completed, int Param = 0, string strParam = null, Object objectParam = null) {
source.destory = false;
this.start++;
if (this.start >= sequence.Count) {
this.start = 0;
if (repeat > 0) repeat--;
if (repeat == 0) {
this.destory = true;
this.callback.SSActionEvent(this);
}
}
}
// Use this for initialization
public override void Start () {
foreach (SSAction action in sequence) {
action.gameobject = this.gameobject;
action.transform = this.transform;
action.callback = this;
action.Start();
}
}
void OnDestory() {}
}
ISSActionCallback.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum SSActionEventType:int {Started, Completed}
public interface ISSActionCallback {
void SSActionEvent(SSAction source,
SSActionEventType events = SSActionEventType.Completed,
int intParam = 0,
string strParam = null,
Object objectParam = null);
}
ISceneController.cs
public interface ISceneController {
void LoadResources();
void Pause();
void Resume();
void Restart();
}
UserGUI.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface IUserAction {
void click();
}
public class UserGUI : MonoBehaviour {
private IUserAction action;
float width, height;
void Start() {
action = SSDirector.getInstance().currentSceneController as IUserAction;
}
float castw(float scale) {
return (Screen.width - width) / scale;
}
float casth(float scale) {
return (Screen.height - height) / scale;
}
void OnGUI() {
width = Screen.width / 12;
height = Screen.height / 12;
GUI.Label(new Rect(castw(2f)+20, casth(6f) - 20, 50, 50), SSDirector.getInstance().leaveSeconds.ToString());// 倒计时秒数 //
if (SSDirector.getInstance().state != State.WIN && SSDirector.getInstance().state != State.LOSE
&& GUI.Button(new Rect(10, 10, 80, 30), SSDirector.getInstance().countDownTitle)) {
if (SSDirector.getInstance().countDownTitle == "Start") {
SSDirector.getInstance().currentSceneController.Resume();
SSDirector.getInstance().countDownTitle = "Pause";
SSDirector.getInstance().onCountDown = true;
StartCoroutine(SSDirector.getInstance().DoCountDown());
} else {
SSDirector.getInstance().currentSceneController.Pause();
SSDirector.getInstance().countDownTitle = "Start";
SSDirector.getInstance().onCountDown = false;
StopAllCoroutines();
}
}
if (SSDirector.getInstance().state == State.WIN) {
StopAllCoroutines();
if (GUI.Button(new Rect(castw(2f), casth(6f), Screen.width / 8, height), "Win!")) SSDirector.getInstance().currentSceneController.Restart();
} else if (SSDirector.getInstance().state == State.LOSE) {
StopAllCoroutines();
if (GUI.Button(new Rect(castw(2f), casth(6f), Screen.width / 7, height), "Lose!")) SSDirector.getInstance().currentSceneController.Restart();
}
}
void Update() {
action.click();
}
}
CCActionManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CCActionManager : SSActionManager, ISSActionCallback {
public FirstController scene;
public CCMoveToAction action1, action2;
public CCSequenceAction saction;
float speed = 30f;
public void moveBoat(GameObject boat) {
action1 = CCMoveToAction.GetSSAction((boat.transform.position == new Vector3(4, 0, 0)? new Vector3(-4, 0, 0) : new Vector3(4, 0, 0)), speed);
this.RunAction(boat, action1, this);
}
public void getOnBoat(GameObject people, int shore, int seat) {
if (shore == 0 && seat == 0) {
action1 = CCMoveToAction.GetSSAction(new Vector3(-5f, 2.7f, 0), speed);
action2 = CCMoveToAction.GetSSAction(new Vector3(-5f, 1.2f, 0), speed);
}
else if(shore==0 && seat == 1) {
action1 = CCMoveToAction.GetSSAction(new Vector3(-3f, 2.7f, 0), speed);
action2 = CCMoveToAction.GetSSAction(new Vector3(-3f, 1.2f, 0), speed);
}
else if (shore == 1 && seat == 0) {
action1 = CCMoveToAction.GetSSAction(new Vector3(3f, 2.7f, 0), speed);
action2 = CCMoveToAction.GetSSAction(new Vector3(3f, 1.2f, 0), speed);
}
else if (shore == 1 && seat == 1) {
action1 = CCMoveToAction.GetSSAction(new Vector3(5f, 2.7f, 0), speed);
action2 = CCMoveToAction.GetSSAction(new Vector3(5f, 1.2f, 0), speed);
}
CCSequenceAction saction = CCSequenceAction.GetSSAction(0, 0, new List<SSAction> { action1, action2 });
this.RunAction(people, saction, this);
}
public void getOffBoat(GameObject people, int shoreNum) {
action1 = CCMoveToAction.GetSSAction(new Vector3(people.transform.position.x, 2.7f, 0), speed);
if (shoreNum == 0) action2 = CCMoveToAction.GetSSAction(new Vector3(-16f + 1.5f * System.Convert.ToInt32(people.name), 2.7f, 0), speed);
else action2 = CCMoveToAction.GetSSAction(new Vector3(16f - 1.5f * System.Convert.ToInt32(people.name), 2.7f, 0), speed);
CCSequenceAction saction = CCSequenceAction.GetSSAction(0, 0, new List < SSAction >{ action1, action2});
this.RunAction(people, saction, this);
}
protected void Start() {
scene = (FirstController)SSDirector.getInstance().currentSceneController;
scene.actionManager = this;
}
protected new void Update() {
base.Update();
}
public void SSActionEvent(SSAction source,SSActionEventType events = SSActionEventType.Completed,
int intParam = 0,
string strParam = null,
Object objectParam = null) {
Debug.Log("Done");
}
}
其中UserGUI是挂在摄像机上的,CCActionManager和FirstController是挂在Main对象上的。
由于代码。。大多数都是参考老师的框架。。所以我先投为转的吧。
效果
gif录制器突然。。找不到了。。找几个过场图片撑撑场面。
结果。。输了。。