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; } }