1.1遊戲對象運動的本質是什麼
遊戲對象運動的本質是遊戲對象随着動畫幀的變化而産生的遊戲對象的坐标以及角度的變化。通過平移、旋轉、縮放的方式改變遊戲對象的transform屬性。
1.2抛物線運動
(1)修改transform
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move1 : MonoBehaviour
{
public float speed = 1;
void Start()
{
}
void Update()
{
transform.position += Vector3.left * 1/10;//水準勻速以速度1前進,放慢十倍
transform.position += Vector3.down * speed * Time.deltaTime/10;//豎直方向以加速度運動,放慢十倍
speed += 10 * Time.deltaTime;//速度随重力改變
}
}
(2)向量Vector3,直接position加上變化向量
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move2 : MonoBehaviour
{
public float speed = 1;
void Start()
{
}
void Update()
{
transform.position += new Vector3(Time.deltaTime * 1,-Time.deltaTime * speed/2,0);//慢放2倍速度
speed += Time.deltaTime * 10;//g=10
}
}
(3)translate一個向量Vector3
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move3 : MonoBehaviour
{
void Start()
{
}
void Update()
{
this.transform.Translate(new Vector3(Time.deltaTime * 1, - 10 / 2 * Time.deltaTime * Time.deltaTime, 0));
}
}
1.3太陽系
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = System.Random;
public class sun : MonoBehaviour
{
// Use this for initialization
private float x0;
void Start()
{
x0= this.transform.position.x;
}
// Update is called once per frame
void Update()
{
this.transform.RotateAround(Vector3.zero, new Vector3(0, x0/10, 2-x0/8), 20 * Time.deltaTime*x0/5);
this.transform.Rotate(Vector3.up * Time.deltaTime * 10000 * x0 / 5);
}
}
運作結果:
2、程式設計實踐
- 遊戲中的對象有:Priests,Devils,boat,one side,the other side
-
玩家動作 條件 開船 船在開始岸、船在結束岸、船上有人 開始岸牧師上船 船在開始岸,船有空位,開始岸有牧師 開始岸魔鬼上船 船在開始岸,船有空位,開始岸有魔鬼 結束岸牧師上船 船在結束岸,船有空位,結束岸有牧師 結束岸魔鬼上船 船在結束岸,船有空位,結束岸有魔鬼 - MVC架構:在Asserts目錄下分别建立Model,Control,View檔案夾
- 将遊戲中對象做成預制
- 整個遊戲僅 主錄影機 和 一個 Empty 對象, 其他對象由代碼動态生成:
- ControlGameObjects.cs
-
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ControlGameObjects : MonoBehaviour { // Start is called before the first frame update public GameObject river; public GameObject boat; public GameObject leftDust; public GameObject rightDust; public GameObject priestOne; public GameObject priestTwo; public GameObject priestThree; public GameObject demonOne; public GameObject demonTwo; public GameObject demonThree; public int CountPeoPleOnBoat; public bool peopleOnBoatLeft; public bool peopleOnBoatRight; public int leftCoastDemonNum; public int leftCoastPriestNum; public int rightCoastDemonNum; public int rightCoastPriestNum; public bool pause; public bool haveEndedGame; void Start() { river = (GameObject)Resources.Load("Prefabs/River"); river = Instantiate(river); boat = (GameObject)Resources.Load("Prefabs/Boat"); boat = Instantiate(boat); leftDust = (GameObject)Resources.Load("Prefabs/DustLeft"); leftDust = Instantiate(leftDust); rightDust = (GameObject)Resources.Load("Prefabs/DustRight"); rightDust = Instantiate(rightDust); priestOne = (GameObject)Resources.Load("Prefabs/priestOne"); priestOne = Instantiate(priestOne); priestTwo = (GameObject)Resources.Load("Prefabs/priestTwo"); priestTwo = Instantiate(priestTwo); priestThree = (GameObject)Resources.Load("Prefabs/priestThree"); priestThree = Instantiate(priestThree); demonOne = (GameObject)Resources.Load("Prefabs/DemonOne"); demonOne = Instantiate(demonOne); demonTwo = (GameObject)Resources.Load("Prefabs/DemonTwo"); demonTwo = Instantiate(demonTwo); demonThree = (GameObject)Resources.Load("Prefabs/DemonThree"); demonThree = Instantiate(demonThree); BeginGame(); } void BeginGame() { haveEndedGame = false; peopleOnBoatRight = false; peopleOnBoatLeft = false; leftCoastDemonNum = 0; leftCoastPriestNum = 0; rightCoastDemonNum = 3; rightCoastPriestNum = 3; pause = false; CountPeoPleOnBoat = 0; // 初始化所有對象 } // Update is called once per frame void Update() { // 如果檢測 if (haveEndedGame && !river.GetComponent<View>().gameEndOrNot) { haveEndedGame = false; BeginGame(); ReStartGame(); } if (!haveEndedGame) { allPeopleClick(); //處理所有人物點選函數 boatClick(); //處理船的點選函數 Checked(); } //檢查遊戲成功或者失敗情況 } public void boatClick() { // 當所有人物運動都是靜止的時候才可以開船; if ((boat.GetComponent<EventClick>().click && CountPeoPleOnBoat <= 0)) boat.GetComponent<EventClick>().click = false; if (boat.GetComponent<EventClick>().click && CountPeoPleOnBoat > 0 && allPeopleStanding()) { if (priestOne.GetComponent<EventClickPeoPle>().onBoat) { priestOne.GetComponent<EventClickPeoPle>().AcrossRiver(); CountPriestsNumOnEachCoast(); } if (demonOne.GetComponent<EventClickPeoPle>().onBoat) { demonOne.GetComponent<EventClickPeoPle>().AcrossRiver(); CountDemonsNumOnEachCoast(); } if (priestTwo.GetComponent<EventClickPeoPle>().onBoat) { priestTwo.GetComponent<EventClickPeoPle>().AcrossRiver(); CountPriestsNumOnEachCoast(); } if (demonTwo.GetComponent<EventClickPeoPle>().onBoat) { demonTwo.GetComponent<EventClickPeoPle>().AcrossRiver(); CountDemonsNumOnEachCoast(); } if (priestThree.GetComponent<EventClickPeoPle>().onBoat) { priestThree.GetComponent<EventClickPeoPle>().AcrossRiver(); CountPriestsNumOnEachCoast(); } if (demonThree.GetComponent<EventClickPeoPle>().onBoat) { demonThree.GetComponent<EventClickPeoPle>().AcrossRiver(); CountDemonsNumOnEachCoast(); } boat.GetComponent<EventClick>().MoveAcrossRiver(); } } public void Checked() // 測試有沒有一岸 魔鬼的數量大于牧師的數量 { //輸了的情況 if (rightCoastPriestNum < rightCoastDemonNum && rightCoastPriestNum != 0) { river.GetComponent<View>().GameEnd("*YOU LOSE*"); haveEndedGame = true; } else if (leftCoastPriestNum < leftCoastDemonNum && leftCoastPriestNum != 0) { river.GetComponent<View>().GameEnd("*YOU LOSE*"); haveEndedGame = true; } else if (river.GetComponent<View>().ShowTime == 0) { river.GetComponent<View>().GameEnd("*YOU LOSE*"); haveEndedGame = true; } //赢了的情況 else if (leftCoastPriestNum == 3 && leftCoastDemonNum == 3 && PeopleNotOnBoat()) // 且所有人不在船上 { river.GetComponent<View>().GameEnd("*YOU WIN*"); haveEndedGame = true; } } public bool PeopleNotOnBoat() { return (!priestOne.GetComponent<EventClickPeoPle>().onBoat) && (!priestTwo.GetComponent<EventClickPeoPle>().onBoat) && (!priestThree.GetComponent<EventClickPeoPle>().onBoat) && (!demonOne.GetComponent<EventClickPeoPle>().onBoat) && (!demonTwo.GetComponent<EventClickPeoPle>().onBoat) && (!demonThree.GetComponent<EventClickPeoPle>().onBoat); } public void ReStartGame() { priestOne.GetComponent<EventClickPeoPle>().begin(); priestTwo.GetComponent<EventClickPeoPle>().begin(); priestThree.GetComponent<EventClickPeoPle>().begin(); demonOne.GetComponent<EventClickPeoPle>().begin(); demonTwo.GetComponent<EventClickPeoPle>().begin(); demonThree.GetComponent<EventClickPeoPle>().begin(); boat.GetComponent<EventClick>().begin(); } public void CountPriestsNumOnEachCoast() { // 動态改變兩岸魔鬼牧師的數量 if (boat.GetComponent<EventClick>().leftSide) // 從左往右 { rightCoastPriestNum += 1; leftCoastPriestNum -= 1; } else { rightCoastPriestNum -= 1; leftCoastPriestNum += 1; } } public void CountDemonsNumOnEachCoast() { if (boat.GetComponent<EventClick>().leftSide) // 從左往右 { rightCoastDemonNum += 1; leftCoastDemonNum -= 1; } else { rightCoastDemonNum -= 1; leftCoastDemonNum += 1; } } public bool allPeopleStanding() { return (priestOne.GetComponent<EventClickPeoPle>().pause && priestTwo.GetComponent<EventClickPeoPle>().pause && priestThree.GetComponent<EventClickPeoPle>().pause && demonOne.GetComponent<EventClickPeoPle>().pause && demonTwo.GetComponent<EventClickPeoPle>().pause && demonThree.GetComponent<EventClickPeoPle>().pause); } public void allPeopleClick() //處理所有人物被點選的事件函數 { // 當船運動的時候所有人不許動 if (!boat.GetComponent<EventClick>().pause) return; if (priestOne.GetComponent<EventClickPeoPle>().click) PeopleClick(ref priestOne); if (priestTwo.GetComponent<EventClickPeoPle>().click) PeopleClick(ref priestTwo); if (priestThree.GetComponent<EventClickPeoPle>().click) PeopleClick(ref priestThree); if (demonOne.GetComponent<EventClickPeoPle>().click) PeopleClick(ref demonOne); if (demonTwo.GetComponent<EventClickPeoPle>().click) PeopleClick(ref demonTwo); if (demonThree.GetComponent<EventClickPeoPle>().click) PeopleClick(ref demonThree); } public void PeopleClick(ref GameObject gobj) { if (gobj.GetComponent<EventClickPeoPle>().LeftOrRight != boat.GetComponent<EventClick>().leftSide) return; // 當船和移動的人物不在同一岸時不能移動 gobj.GetComponent<EventClickPeoPle>().click = false; if (!gobj.GetComponent<EventClickPeoPle>().onBoat) // 當牧師不在船上的時候 { if (CountPeoPleOnBoat >= 2) return; CountPeoPleOnBoat += 1; if (!peopleOnBoatLeft) { gobj.GetComponent<EventClickPeoPle>().MovePeoPle(1); peopleOnBoatLeft = true; } else { gobj.GetComponent<EventClickPeoPle>().MovePeoPle(2); peopleOnBoatRight = true; } } else { int onBoatLeftOrRight = gobj.GetComponent<EventClickPeoPle>().onBoatLeftOrRight; if (onBoatLeftOrRight == 1) { peopleOnBoatLeft = false; } else { peopleOnBoatRight = false; } gobj.GetComponent<EventClickPeoPle>().MovePeoPle(onBoatLeftOrRight); CountPeoPleOnBoat -= 1; } } }
- EventClick.cs
-
using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using UnityEngine; using UnityEngine.EventSystems; public class EventClick : MonoBehaviour, IPointerClickHandler { public bool leftSide; public bool pause; public bool click; public Transform boat; // public float time; // Start is called before the first frame update void Start() { leftSide = false; // true為左邊,false為右邊; pause = true; } // Update is called once per frame void Update() { if (!pause) { if (leftSide) { boat.position = Vector3.MoveTowards(boat.localPosition, new Vector3((float)1.3, (float)0.4, (float)-1), (float)2 * Time.deltaTime); if (boat.position == new Vector3((float)1.3, (float)0.4, (float)-1)) { pause = true; leftSide = false; } } else { boat.position = Vector3.MoveTowards(boat.localPosition, new Vector3((float)-1.3, (float)0.4, (float)-1), (float)2 * Time.deltaTime); if (boat.position == new Vector3((float)-1.3, (float)0.4, (float)-1)) { pause = true; leftSide = true; } } } } public void OnPointerClick(PointerEventData eventData) { if (!pause) return; click = true; } public void MoveAcrossRiver() { click = false; pause = false; } public void begin() { boat.position = new Vector3((float)1.3, (float)0.4, (float)-1); pause = true; leftSide = false; } }
- EventClickPeoPle.cs
-
using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Security.Cryptography; using UnityEngine; using UnityEngine.EventSystems; public class EventClickPeoPle : MonoBehaviour, IPointerClickHandler { public bool pause; public bool onBoat; public Transform person; public bool LeftOrRight; //人在左邊還是右邊,左邊:true //以河的中心區分左右 public Vector3 onBoatPosition; public int onBoatLeftOrRight; //人在上船後,在船的左邊還是右邊;以在河的右邊為例。如果在河的左邊,則是鏡像。 1為右邊,2為左。0為不在船上 public Vector3 leftStartPosition; public Vector3 leftFirstDestination; public Vector3 leftMidDestination; public Vector3 leftFinalDestination; public Vector3 rightStartPosition; public Vector3 rightFirstDestination; public Vector3 rightMidDestination; public Vector3 rightFinalDestination; public bool leftZeroStep; public bool leftFistStep; public bool leftMidStep; public bool leftFinalStep; public bool rightZeroStep; // 從第一個位置點傳回起始位置 public bool rightFistStep; public bool rightMidStep; public bool rightFinalStep; public bool rightToBoat; public bool boatToRight; public bool leftToBoat; public bool boatToLeft; public bool leftAcrossRiver; // 從河的右邊到左邊 public bool rightAcrossRiver; // 從河的左邊到右邊 public bool finishAcrossed; // 是否度過了河 public bool finishOnBoatPosition; // 是否到船上準确位置 public bool click; // 被點選。與ModelGameObject互動 // public float time; // Start is called before the first frame update void Start() { changePosition(person.position); begin(); } public void begin() { onBoatLeftOrRight = 0; click = false; LeftOrRight = false; leftZeroStep = false; leftFistStep = false; leftMidStep = false; leftFinalStep = false; rightZeroStep = false; rightFistStep = false; rightMidStep = false; rightFinalStep = false; onBoat = false; pause = true; rightToBoat = false; boatToRight = false; leftToBoat = false; boatToLeft = false; leftAcrossRiver = false; rightAcrossRiver = false; finishAcrossed = false; finishOnBoatPosition = false; person.position = rightStartPosition; } public void changePosition(Vector3 position) { float para = 1; if (position.x < 0) para = -1; rightStartPosition = position; rightFirstDestination = new Vector3(position.x, position.y + (float)0.55, position.z); rightMidDestination = new Vector3((float)1.25 * para, rightFirstDestination.y, rightFirstDestination.z); rightFinalDestination = new Vector3(rightMidDestination.x, (float)0.8, rightMidDestination.z); leftStartPosition = new Vector3((float)-1 * rightStartPosition.x, rightStartPosition.y, rightStartPosition.z); leftFirstDestination = new Vector3((float)-1 * position.x, position.y + (float)0.55, position.z); leftMidDestination = new Vector3((float)-1.5, rightFirstDestination.y, rightFirstDestination.z); leftFinalDestination = new Vector3((float)-1 * rightMidDestination.x, (float)0.8, rightMidDestination.z); } // Update is called once per frame void Update() { if (pause) return; if (rightToBoat) { if (!MoveToBoat(ref rightFistStep, rightFirstDestination)) return; if (!MoveToBoat(ref rightMidStep, rightMidDestination)) return; if (!MoveToBoat(ref rightFinalStep, rightFinalDestination)) return; if (!MoveToBoat(ref finishOnBoatPosition, onBoatPosition)) return; finishOnBoatPosition = false; onBoat = true; pause = true; rightToBoat = false; rightZeroStep = false; rightFistStep = false; rightMidStep = false; rightFinalStep = false; } else if (boatToRight) { if (!MoveToBoat(ref rightFinalStep, rightFinalDestination)) return; if (!MoveToBoat(ref rightMidStep, rightMidDestination)) return; if (!MoveToBoat(ref rightFistStep, rightFirstDestination)) return; if (!MoveToBoat(ref rightZeroStep, rightStartPosition)) return; onBoat = false; pause = true; boatToRight = false; rightZeroStep = false; rightFistStep = false; rightMidStep = false; rightFinalStep = false; } else if (leftToBoat) { if (!MoveToBoat(ref leftFistStep, leftFirstDestination)) return; if (!MoveToBoat(ref leftMidStep, leftMidDestination)) return; if (!MoveToBoat(ref leftFinalStep, leftFinalDestination)) return; if (!MoveToBoat(ref finishOnBoatPosition, onBoatPosition)) return; finishOnBoatPosition = false; onBoat = true; pause = true; leftToBoat = false; leftZeroStep = false; leftFistStep = false; leftMidStep = false; leftFinalStep = false; } else if (boatToLeft) { if (!MoveToBoat(ref leftFinalStep, leftFinalDestination)) return; if (!MoveToBoat(ref leftMidStep, leftMidDestination)) return; if (!MoveToBoat(ref leftFistStep, leftFirstDestination)) return; if (!MoveToBoat(ref leftZeroStep, leftStartPosition)) return; onBoat = false; pause = true; boatToLeft = false; leftZeroStep = false; leftFistStep = false; leftMidStep = false; leftFinalStep = false; } else if (leftAcrossRiver) // 從左到右渡河 { if (!MoveAcrossRiver(ref finishAcrossed, onBoatPosition)) return; pause = true; finishAcrossed = false; leftAcrossRiver = false; } else if (rightAcrossRiver) { if (!MoveAcrossRiver(ref finishAcrossed, onBoatPosition)) return; pause = true; finishAcrossed = false; rightAcrossRiver = false; } } public void AcrossRiver() { if (!onBoat || !pause) return; if (!LeftOrRight) { LeftOrRight = true; rightAcrossRiver = true; onBoatPosition = new Vector3((float)-2.5 + onBoatPosition.x, (float)0.8, (float)-1.1); } else { LeftOrRight = false; leftAcrossRiver = true; //leftAcroossRiver 從左到右渡河 onBoatPosition = new Vector3((float)2.5 + onBoatPosition.x, (float)0.8, (float)-1.1); } pause = false; } public void OnPointerClick(PointerEventData eventData) { if (!pause) return; // 請求ModleGameObject響應 click = true; return; } public void MovePeoPle(int t_onBoatPosition) // On...: 1代表在船的左邊,2代表在船的右邊; { // 選擇路徑 if (!onBoat && !LeftOrRight) { rightToBoat = true; } else if (onBoat && !LeftOrRight) { boatToRight = true; } else if (!onBoat && LeftOrRight) { leftToBoat = true; } else if (onBoat && LeftOrRight) { boatToLeft = true; } bool right = false; if (rightToBoat || boatToRight) right = true; if (right) { if (t_onBoatPosition == 1) { onBoatPosition = new Vector3((float)1, (float)0.8, (float)-1.1); onBoatLeftOrRight = 1; } else if (t_onBoatPosition == 2) { onBoatPosition = new Vector3((float)1.5, (float)0.8, (float)-1.1); onBoatLeftOrRight = 2; } }else { if (t_onBoatPosition == 1) { onBoatPosition = new Vector3((float)-1.5, (float)0.8, (float)-1.1); onBoatLeftOrRight = 1; } else if (t_onBoatPosition == 2) { onBoatPosition = new Vector3((float)-1, (float)0.8, (float)-1.1); onBoatLeftOrRight = 2; } } pause = false; } bool MoveToBoat(ref bool step, Vector3 destination) { if (step) return step; person.position = Vector3.MoveTowards(person.localPosition,destination, (float)5 * Time.deltaTime); if (person.position == destination) { step = true; } return step; } bool MoveAcrossRiver(ref bool step, Vector3 destination) { if (step) return step; person.position = Vector3.MoveTowards(person.localPosition, destination, (float)2 * Time.deltaTime); if (person.position == destination) { step = true; } return step; } }
- View.cs
-
using System.Collections; using System.Collections.Generic; using UnityEngine; public class View : MonoBehaviour { // Start is called before the first frame update private float time; public int ShowTime; // 顯示時間是整數 public string ShowMessage; public bool gameEndOrNot; public bool gameReStart; void Start() { begin(); } // Update is called once per frame void Update() { if(!gameEndOrNot) { time -= Time.deltaTime; ShowTime = (int)time; } } void OnGUI() { //小字型初始化 GUIStyle style = new GUIStyle(); style.normal.textColor = Color.white; style.fontSize = 20; //大字型初始化 GUIStyle bigStyle = new GUIStyle(); bigStyle.normal.textColor = Color.white; bigStyle.fontSize = 30; GUI.Label(new Rect(150, 0, 50, 200), "Priests and Devils", bigStyle); GUI.Label(new Rect(0, 30, 100, 50), "Time: " + ShowTime, style); bigStyle.normal.textColor = Color.red; bigStyle.fontSize = 50; // "*YOU LOSE*" "*YOU WIN*" // 遊戲結束 if (gameEndOrNot) { if (GUI.Button(new Rect(240, 110, 100, 50), "RESTART")) { begin(); } GUI.Label(new Rect(120, 50, 50, 200), ShowMessage, bigStyle); } } public void GameEnd(string t_showMessage) { ShowMessage = t_showMessage; gameEndOrNot = true; } public void begin() { ShowMessage = ""; time = 60; ShowTime = 60; gameReStart = false; gameEndOrNot = false; } }