乐趣区

关于unity3d:空间与运动-MVC架构学习

空间与静止 — MVC 架构学习

简答并用程序验证【倡议做】

  • 游戏对象静止的实质是什么?
  • 请用三种办法以上办法,实现物体的抛物线静止。(如,批改 Transform 属性,应用向量 Vector3 的办法…)
  • 写一个程序,实现一个残缺的太阳系,其余星球围绕太阳的转速必须不一样,且不在一个法平面上。

解答:

  • 静止的实质就是扭转 transform 三个属性的 (Position, Rotation, Scale) 值,使物体进行静止

抛物线静止实现的三种办法:

  • 扭转物体 position 的办法,因为要实现抛物线静止,咱们晓得在 unity 的界面中,垂直方向的扭转也就是对 y 轴进行扭转,依据抛物线的公式 $y=v_0t+\frac{1}{2}at^2$, 抛物线是向下静止就能够在公式中增加负号,即可实现物体的想下静止

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class NewBehaviourScript : MonoBehaviour
      {
          public float vx = 0.5f; // x 轴方向上的速度
          public float v0 = 0; // y 轴方向上的初始速度
          const float a = 9.8f; // 加速度 a
          // Start is called before the first frame update
          void Start()
          { }
      
      // Update is called once per frame
      void Update()
      {this.transform.position += new Vector3(vx * Time.deltaTime, (float)(-v0 * Time.deltaTime - 0.5 * a * (Time.deltaTime) * (Time.deltaTime)), 0);
          v0 += a * Time.deltaTime; // 每一帧扭转的时候 v0 的速度是不一样的
      }
    }
    • 应用 transform 的 translate 函数,此函数使得物体的 position 挪动相应的地位,具体的公式还是抛物线的公式:$y=v_0t+\frac{1}{2}at^2$
      using System.Collections;
      using System.Collections.Generic;
      using UnityEngine;
      
      public class NewBehaviourScript : MonoBehaviour
      {
          public float vx = 0.5f; // x 轴方向上的速度
          public float v0 = 0; // y 轴方向上的初始速度
          const float a = 9.8f; // 加速度 a
          // Start is called before the first frame update
          void Start()
          { }
      
          // Update is called once per frame
          void Update()
          {this.transform.Translate(new Vector3(vx * Time.deltaTime, (float)(-v0 * Time.deltaTime - 0.5 * a * (Time.deltaTime) * (Time.deltaTime)), 0));
              v0 += a * Time.deltaTime;
          }
      }
    • transform 中能够调用一个函数 SetPositionAndRotation,此函数能够设置物体的 position 和 rotation,rotation 能够不须要设置,position 设置的数值和下面基本一致,然而此时须要额定设置工夫的变动,以及,初始物体的高度也就是 y 值
      using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class NewBehaviourScript : MonoBehaviour
    {
        public float vx = 0.5f; // x 轴方向上的速度
        const float a = 9.8f; // 加速度 a
        public float t = 0;
        public float y = 10.0f; // 初始 y 的地位
        // Start is called before the first frame update
        void Start()
        { }
    
        // Update is called once per frame
        void Update()
        {this.transform.SetPositionAndRotation(new Vector3(vx * t, y - (float)(0.5 * a * t * t), 10), this.transform.rotation);
            t += Time.deltaTime;
        }
    }
    • 做太阳系,首先从老师给的网址太阳系贴图,将所有行星的图片都拖到桌面,而后再拖入 unity 中,即可在 assets 中应用,而后将这些图片拖到大小不一的球星就够,就能够造成各大行星

      依据老师上课给的代码,进行肯定的批改,即可实现整个太阳系的行星围绕太阳转动的现象

      也能够看到几大行星并不是在一个法平面上,所以实现了要求

      using System.Collections;
      using System.Collections.Generic;
      using UnityEngine;
      
      public class Rotate : MonoBehaviour
      {
          public int v; // 旋转的速度
          public Vector3 e;
          float x, y; // 法向量
          // Start is called before the first frame update
          void Start()
          {
              // 因为在不同的法平面所以生成的法向量应该是随机的
              x = Random.Range(1, 10); y = Random.Range(10, 20);
              e = new Vector3(x, y, 0);
          }
          // Update is called once per frame
          void Update()
          {Quaternion q = Quaternion.AngleAxis(v * Time.deltaTime, e);
              this.transform.localPosition = q * this.transform.localPosition;
          }
      }
      

      下面代码的法向量是随机生成的故不在同一个法平面,速度能够本人设置故能够行星绕着太阳旋转的速度不一样

    编程实际

    • 浏览以下游戏脚本

    Priests and Devils

    Priests and Devils is a puzzle game in which you will help the Priests and Devils to cross the river within the time limit. There are 3 priests and 3 devils at one side of the river. They all want to get to the other side of this river, but there is only one boat and this boat can only carry two persons each time. And there must be one person steering the boat from one side to the other side. In the flash game, you can click on them to move them and click the go button to move the boat to the other direction. If the priests are out numbered by the devils on either side of the river, they get killed and the game is over. You can try it in many > ways. Keep all priests alive! Good luck!

    程序须要满足的要求:

    • play the game (http://www.flash-game.net/gam…)
    • 列出游戏中提及的事物(Objects)
    • 用表格列出玩家动作表(规定表),留神,动作越少越好
    • 请将游戏中对象做成预制
    • 在场景控制器 LoadResources 办法中加载并初始化长方形、正方形、球及其色调代表游戏中的对象。
    • 应用 C# 汇合类型无效组织对象
    • 整个游戏仅主摄像机和一个 Empty 对象,其余对象必须代码动静生成!!。整个游戏不许呈现 Find 游戏对象,SendMessage 这类冲破程序结构的 通信耦合 语句。违反本条准则,不给分
    • 请应用课件架构图编程,不承受非 MVC 构造程序
    • 留神细节,例如:船未靠岸,牧师与魔鬼高低船静止中,均不能承受用户事件!

    游戏规则

    牧师与魔鬼:这是一款经典的游戏,游戏很简略,玩家须要操控船只、牧师和魔鬼,而后使得一个岸边的三个牧师和三个魔鬼都挪动到另一个岸边。并且须要在游戏限定的工夫 60 秒内进行操作。

    留神

    • 要想使船挪动,船上必须有牧师或魔鬼
    • 船上最多有两个人物
    • 不论哪个岸上,只有魔鬼数大于牧师数游戏失败(数量包含船只停泊时船上的人物数量)

    游戏资源

    github 地址

    游戏截图和视频

    因为游戏过程比拟长,所以只截取局部过程图,具体游戏的过程在视频链接中

    视频链接


    游戏 Assets 构造

    设计的构造齐全是依照规范的构造构建的,如下图所示

    • Materials:寄存游戏中的 Material
    • Resources:寄存游戏中的对象的预制
    • Scenes:寄存游戏的场景
    • Scripts:寄存游戏的 c# 代码
    • Texture:寄存对于物体的一些图片

    游戏中的事物

    • Water:水,也就是牧师与魔鬼须要度过的,由长方体形成,并挂上网上找的图片
    • Devil:魔鬼,由彩色的长方体形成
    • Priest:牧师,由绿色的长方体形成
    • ground:两个岸边,由长方体形成,并挂上图片
    • Boat:木船,由长方体形成,并挂上图片

    MVC 构造编程

    在进行编程前,须要理解 MVC 的大体构造

    MVC 是界面人机交互程序设计的一种架构模式。它把程序分为三个局部:

    • 模型(Model):数据对象及关系

      • 游戏对象、空间关系
    • 控制器(Controller):承受用户事件,管制模型的变动

      • 一个场景一个主控制器
      • 至多实现与玩家交互的接口(IPlayerAction)
      • 实现或治理静止
    • 界面(View):显示模型,将人机交互事件交给控制器解决

      • 处收 Input 事件
      • 渲染 GUI,接管事件

    本试验也是严格依照了 MVC 构造进行编写代码,代码的大抵形成,如下图所示:

    类中的变量因为权限不同设置成了不同的类型,public,private,readonly(只读变量不能够对它的值进行批改)

    接下来别离介绍各个代码实现的具体性能:

    • Director:属于最高层的控制器,放弃运行时始终有一个实例,这样不便了类与类之间的通信。

      次要的职责有:

      • 获取以后游戏的场景
      • 管制场景运行、切换、入栈与出栈
      • 暂停、复原、退出
      • 治理游戏全局状态
      • 设定游戏的配置
      • 设定游戏全局视图

    能够通过一个形象的场景接口拜访不同场景的控制器

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    // 负责实例化
    public class Director : System.Object {
        private static Director _instance;
        public SceneController currentSceneController {get; set;}
    
        public static Director getInstance() {if (_instance == null)  _instance = new Director ();
            return _instance;
        }
    }
    • SceneController:场景控制器:

      职责:

      • 治理本次场景所有的游戏对象
      • 协调游戏对象(预制件级别)之间的通信
      • 响应内部输出事件
      • 治理本场次的规定(裁判)
      • 各种杂务

    能够看到它是由 interface 实现的,阐明不能间接来创建对象,咱们通过之前的学习能够晓得,interface 的应用须要一个类去继承它,这样才能够应用。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    // 场景治理:加载所有的资源
    public interface SceneController {void LoadResources ();
    }
    • RoleController:由类的名字就能够晓得,这是对游戏人物的控制器,能够管制人物的挪动,并且能够失去人物的相干信息,比方该游戏人物是牧师还是魔鬼,在船上还是在岸上,该游戏人物的名字是什么等等。不光须要以上的性能,因为人物是能够操控的所以咱们还须要监控鼠标对人物的点击性能。
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    // 对游戏人物的控制器
    public class RoleController {
        readonly GameObject obj;
        readonly Moving mov;
        readonly ClickGUI clickGUI;
        readonly int PorD; // 判断是牧师 (0) 还是魔鬼(1)
    
        bool _isOnBoat;
        GroundController gController;
    
        public RoleController(string r) {if (r == "priest") {obj = Object.Instantiate (Resources.Load ("Perfabs/Priest", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
                PorD = 0;
            } else {obj = Object.Instantiate (Resources.Load ("Perfabs/Devil", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
                PorD = 1;
            }
            mov = obj.AddComponent (typeof(Moving)) as Moving;
    
            clickGUI = obj.AddComponent (typeof(ClickGUI)) as ClickGUI;
            clickGUI.setController (this);
        }
    
        public void setName(string n) {obj.name = n;}
    
        public void setPosition(Vector3 p) {obj.transform.position = p;}
    
        public void Movingto(Vector3 dest) {mov.setDestination(dest);
        }
    
        public int getRole() {return PorD;}
    
        public string getName() {return obj.name;}
    
        public void getOnBoat(BoatController b) {
            gController = null;
            obj.transform.parent = b.getGameobj().transform;
            _isOnBoat = true;
        }
    
        public void getGround(GroundController coastCtrl) {
            gController = coastCtrl;
            obj.transform.parent = null;
            _isOnBoat = false;
        }
    
        public bool isOnBoat() {return _isOnBoat;}
    
        public GroundController getGroundController() {return gController;}
    
        public void reset() {mov.reset ();
            gController = (Director.getInstance ().currentSceneController as FirstController).g1;
            getGround (gController);
            setPosition (gController.getEmptyPosition ());
            gController.getGround (this);
        }
    }
    • GroundController:对高空的控制器,两个只读变量 sPosition、ePosition 记录了两个高空的地位,而后 pos 数组记录了海洋上的可寄存人物的地位;上海洋和下海洋的动作对变量的批改;有上海洋之前,须要判断海洋上的空地位的索引,而后才能够批改变量的内容
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    // 海洋的控制器
    public class GroundController {
        readonly GameObject ground;
        readonly Vector3 sPosition = new Vector3(9, 1, 0);
        readonly Vector3 ePosition = new Vector3(-9, 1, 0);
        readonly Vector3[] pos;
        readonly int st_pos;
    
        RoleController[] roles;
    
        public GroundController(string ss) {pos = new Vector3[] {new Vector3(6.5F,2.25F,0), new Vector3(7.5F,2.25F,0), new Vector3(8.5F,2.25F,0), 
                new Vector3(9.5F,2.25F,0), new Vector3(10.5F,2.25F,0), new Vector3(11.5F,2.25F,0)};
    
            roles = new RoleController[6];
    
            if (ss == "from") {ground = Object.Instantiate (Resources.Load ("Perfabs/Ground", typeof(GameObject)), sPosition, Quaternion.identity, null) as GameObject;
                ground.name = "from";
                st_pos = 1;
            } else {ground = Object.Instantiate (Resources.Load ("Perfabs/Ground", typeof(GameObject)), ePosition, Quaternion.identity, null) as GameObject;
                ground.name = "to";
                st_pos = -1;
            }
        }
    
        public int getEmptyIndex() {for (int i = 0; i < roles.Length; i++) {if (roles [i] == null) return i;
            }
            return -1;
        }
    
        public Vector3 getEmptyPosition() {Vector3 p = pos [getEmptyIndex ()];
            p.x *= st_pos;
            return p;
        }
    
        public void getGround(RoleController r) {int ii = getEmptyIndex ();
            roles [ii] = r;
        }
    
        public RoleController getOffGround(string pname) {    // 0->priest, 1->devil
            for (int i = 0; i < roles.Length; i++) {if (roles [i] != null && roles [i].getName () == pname) {RoleController r = roles [i];
                    roles [i] = null;
                    return r;
                }
            }
            return null;
        }
    
        public int get_st_pos() {return st_pos;}
    
        public int[] getRoleNum() {int[] cnt = {0, 0};
            for (int i = 0; i < roles.Length; i++) {if (roles [i] == null) continue;
    
                if (roles [i].getRole () == 0) cnt[0]++;
                else cnt[1]++;
            }
            return cnt;
        }
    
        public void reset() {roles = new RoleController[6];
        }
    }
    • BoatController:对船的控制器,有两个只读变量 sPosition,ePosition,来示意船的起始和终止地位,并且通过变量st_pos 来判断是终点还是起点,还须要对船进行管制静止,所以须要监听鼠标的点击性能。还须要判断该船是否为空,还有空的地位所对应的索引,还须要失去上船下船等动作的告诉;该类的实现和下面的海洋控制器的实现类似,所以设计起来也比较简单
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    // 船的控制器
    public class BoatController {
        readonly GameObject boat;
        readonly Moving mov;
        readonly Vector3 sPosition = new Vector3 (5, 1, 0); // 起始地位
        readonly Vector3[] sPositions;
        readonly Vector3 ePosition = new Vector3 (-5, 1, 0); // 达到地位
        readonly Vector3[] ePositions;
    
        int st_pos; // 起始点还是起点:-1: 起点 1: 终点
        RoleController[] member = new RoleController[2];
    
        public BoatController() {
            st_pos = 1;
    
            sPositions = new Vector3[] { new Vector3 (4.5F, 1.5F, 0), new Vector3 (5.5F, 1.5F, 0) };
            ePositions = new Vector3[] { new Vector3 (-5.5F, 1.5F, 0), new Vector3 (-4.5F, 1.5F, 0) };
    
            boat = Object.Instantiate (Resources.Load ("Perfabs/Boat", typeof(GameObject)), sPosition, Quaternion.identity, null) as GameObject;
            boat.name = "boat";
    
            mov = boat.AddComponent (typeof(Moving)) as Moving;
            boat.AddComponent (typeof(ClickGUI));
        }
    
    
        public void Move() {if (st_pos == -1) {mov.setDestination(sPosition);
                st_pos = 1;
            } else {mov.setDestination(ePosition);
                st_pos = -1;
            }
        }
    
        public int getEmptyIndex() {for (int i = 0; i < member.Length; i++) {if (member [i] == null) return i;
            }
            return -1;
        }
    
        public bool isEmpty() {for (int i = 0; i < member.Length; i++) {if (member [i] != null) return false;
            }
            return true;
        }
    
        public Vector3 getEmptyPosition() {
            Vector3 p;
            int ii = getEmptyIndex ();
            if (st_pos == -1) p = ePositions[ii];
            else p = sPositions[ii];
            
            return p;
        }
    
        public void GetOnBoat(RoleController r) {int ii = getEmptyIndex ();
            member [ii] = r;
        }
    
        public RoleController GetOffBoat(string member_name) {for (int i = 0; i < member.Length; i++) {if (member [i] != null && member [i].getName () == member_name) {RoleController r = member [i];
                    member [i] = null;
                    return r;
                }
            }
            return null;
        }
    
        public GameObject getGameobj() {return boat;}
    
        public int get_st_pos() {return st_pos;}
    
        public int[] getRoleNum() {int[] cnt = {0, 0};
            for (int i = 0; i < member.Length; i++) {if (member [i] == null) continue;
    
                if (member [i].getRole () == 0) cnt[0]++;
                else cnt[1]++;
            }
            return cnt;
        }
    
        public void reset() {mov.reset ();
            if (st_pos == -1) Move ();
            
            member = new RoleController[2];
        }
    }
    • Moving:是一个对于对象静止的类,该类能够管制物体的挪动速度speed,还能够设置物体的目的地,以达到物体能够挪动。因为岸上的人物要想达到船上须要通过两个步骤,否则可能会穿模,也就是人物会穿过地外表,这样会不谨严,所以我设置了 cur 变量来判断以后物体运行的地位,而后再依据地位设置相应的目的地(mid, dest),来解决此类问题。
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    // 对于对象静止的实现
    public class Moving: MonoBehaviour {
            
        readonly float speed = 20;
    
        int cur; // 以后运行的地位
        Vector3 dest, mid; // 设置一个两头地位,使得静止不会穿模
    
        public void setDestination(Vector3 d) {
            dest = d; mid = d;
    
            if (d.y == transform.position.y) cur = 2;
            else if (d.y < transform.position.y) mid.y = transform.position.y;
            else mid.x = transform.position.x;
            
            cur = 1;
        }
    
        public void reset() {cur = 0;}
    
        void Update() {if (cur == 1) {transform.position = Vector3.MoveTowards (transform.position, mid, speed * Time.deltaTime);
                if (transform.position == mid) cur = 2;
            } else if (cur == 2) {transform.position = Vector3.MoveTowards (transform.position, dest, speed * Time.deltaTime);
                if (transform.position == dest) cur = 0;
            }
        }
    }
    • FirstController:高一层的控制器,管制着这个场景中的所有对象,包含其加载、通信、用户输出。

      继承了SceneControllerUserAction,阐明该控制器实现了对两个接口的继承并实现;该控制器还实现了加载游戏资源和加载游戏人物,并且有管制人物静止和船只的静止;游戏的运行工夫的管制;判断游戏是否完结,和游戏完结的条件,如果完结了进行重置游戏,从新设置各个变量

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    // 总控制器
    public class FirstController : MonoBehaviour, SceneController, UserAction {readonly Vector3 p_water = new Vector3(0,0.5F,0); // 水的地位
        
        UserGUI uGUI;
    
        public GroundController g1;
        public GroundController g2;
        public BoatController boat;
        private RoleController[] roles; 
        private float time; // 游戏运行的工夫
    
        void Awake() {Director d = Director.getInstance ();
            d.currentSceneController = this;
            uGUI = gameObject.AddComponent <UserGUI>() as UserGUI;
            roles = new RoleController[6];
            LoadResources();
            time = 60;
        }
    
        // 游戏工夫的运行
        void Update() {
            time -= Time.deltaTime;
            this.gameObject.GetComponent<UserGUI>().time = (int) time;
            uGUI.isWin = isfinished ();}
    
        private void loadRole() {for (int i = 0; i < 3; i++) {RoleController r = new RoleController ("priest");
                r.setName("priest" + i);
                r.setPosition (g1.getEmptyPosition ());
                r.getGround (g1); g1.getGround (r);
    
                roles [i] = r;
            }
    
            for (int i = 0; i < 3; i++) {RoleController r = new RoleController ("devil");
                r.setName("devil" + i);
                r.setPosition (g1.getEmptyPosition ());
                r.getGround (g1); g1.getGround (r);
    
                roles [i+3] = r;
            }
        }
    
        public void LoadResources() {GameObject water = Instantiate (Resources.Load ("Perfabs/Water", typeof(GameObject)), p_water, Quaternion.identity, null) as GameObject;
            water.name = "water";
    
            g1 = new GroundController ("from");
            g2 = new GroundController ("to");
            boat = new BoatController ();
    
            loadRole ();}
    
        public void MoveBoat() {if (boat.isEmpty ()) return;
            boat.Move ();
            uGUI.isWin = isfinished ();}
    
        public void MoveRole(RoleController r) {if (r.isOnBoat ()) {
                GroundController which_g;
                if (boat.get_st_pos () == -1) which_g = g2;
                else which_g = g1;
                
                boat.GetOffBoat (r.getName());
                r.Movingto (which_g.getEmptyPosition ());
                r.getGround (which_g);
                which_g.getGround (r);
            } else {GroundController which_g = r.getGroundController ();
    
                if (boat.getEmptyIndex () == -1) return; // 船是空的        
                if (which_g.get_st_pos () != boat.get_st_pos ()) return;
    
                which_g.getOffGround(r.getName());
                r.Movingto (boat.getEmptyPosition());
                r.getOnBoat (boat);
                boat.GetOnBoat (r);
            }
            uGUI.isWin = isfinished ();}
    // 判断是否完结 0: 没有完结 1: 输 2: 赢
        int isfinished() {if (time < 0) return 1;
            int p1 = 0; int d1 = 0; // 起始点牧师与魔鬼数量
            int p2 = 0; int d2 = 0; // 起点牧师与魔鬼数量
    
            int[] cnt1 = g1.getRoleNum (); // 起始点的人数
            p1 += cnt1[0]; d1 += cnt1[1];
    
            int[] cnt2 = g2.getRoleNum (); // 起点的人数
            p2 += cnt2[0]; d2 += cnt2[1];
    
            if (p2 + d2 == 6) return 2;
    
            int[] cnt3 = boat.getRoleNum (); // 船上人的数量
            if (boat.get_st_pos () == -1) {p2 += cnt3[0]; d2 += cnt3[1];
            } else {p1 += cnt3[0]; d1 += cnt3[1];
            }
    
            if (p1 < d1 && p1 > 0) return 1;
            if (p2 < d2 && p2 > 0) return 1;
            return 0;            
        }
    
        public void restart() {
            time = 60;
            boat.reset ();
            g1.reset (); g2.reset ();
            for (int i = 0; i < roles.Length; i++) roles [i].reset ();}
    }
    
    • UserAction:接口,定义了玩家能够进行的操作 MoveBoat() 挪动船只、MoveRole 挪动人物、restart 从新开始游戏。该接口通过别的类来继承,这样就能够实现失去用户的输出而后作出反应
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    // 用户或玩家能够进行的操作
    public interface UserAction {void MoveBoat();
        void MoveRole(RoleController r);
        void restart();}
    • UserGUI:用户交互,来设置整个用户界面,判断游戏是否胜利,如果胜利则显示Win,并有一个按钮示意是否须要从新玩这个游戏;如果失败则会显示GameOver,而后也能够进行游戏重置。在此我还设置了字体的大小和按钮的大小,不便观看,也不失美感
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class UserGUI : MonoBehaviour {
        private UserAction u;
        public int isWin = 0;// 1:Gameover 2:Win
        public int time; // 游戏运行工夫
        GUIStyle ssize, buttons, tsize;
    
        void Start() {u = Director.getInstance ().currentSceneController as UserAction;
    
            // 设置字体大小
            ssize = new GUIStyle(); tsize = new GUIStyle();
            ssize.fontSize = 45; tsize.fontSize = 20;
            ssize.alignment = TextAnchor.MiddleCenter;
    
            // 设置按钮大小
            buttons = new GUIStyle("button");
            buttons.fontSize = 30;
    
            // 设置游戏的时长
            time = 60;
        }
        // 判断是否胜利或失败,而后重置
        void OnGUI() {GUI.Label(new Rect(0, 0, 100, 50), "Time:" + time, tsize);
            if (isWin == 1) {GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height / 2 - 80, 100, 50), "Gameover!", ssize);
                if (GUI.Button(new Rect(Screen.width / 2-65, Screen.height / 2, 140, 70), "Restart", buttons)) {isWin = 0; u.restart ();
                }
            } else if(isWin == 2) {GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height / 2 - 80, 100, 50), "Win!", ssize);
                if (GUI.Button(new Rect(Screen.width / 2 - 65, Screen.height / 2, 140, 70), "Restart", buttons)) {isWin = 0; u.restart ();
                }
            }
        }
    }
    
    • ClickGUI:用来监听鼠标的点击性能,并且调用 RoleController 实现对人物的管制
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    // 鼠标点击的管制
    public class ClickGUI : MonoBehaviour {
        UserAction u;
        RoleController roleController;
    
        public void setController(RoleController rc) {roleController = rc;}
    
        void Start() {u = Director.getInstance ().currentSceneController as UserAction;
        }
    
        void OnMouseDown() {if (gameObject.name == "boat") u.MoveBoat ();
            else u.MoveRole (roleController);
        }
    }

    思考题【选做】

    • 应用向量与变换,实现并扩大 Tranform 提供的办法,如 Rotate、RotateAround 等

    解答:

    • Rotate:

      Rotates the object around the given axis by the number of degrees defined by the given angle.

      Rotate has an axis, angle and the local or global parameters. The rotation axis can be in any direction.

      须要实现绕 v 轴旋转角度 x,失去了旋转之后,就能够扭转 t 的 position 和 rotation

      void Rotate(Transform t, Vector3 axis, float angle)
      {var r = Quaternion.AngleAxis(angle, axis);
          t.position = r * t.position; t.rotation *= r;
      }
    • RotateAround:

      Rotates the transform about axis passing through point in world coordinates by angle degrees.

      此函数是围绕核心旋转,咱们须要失去物体的位移,求完之后,将它进行旋转而后加上核心的位移即可。

      void RotateAround(Transform t, Vector3 center, Vector3 axis, float angle)
    {var r = Quaternion.AngleAxis(angle, axis);
        var dis = t.position - center;
        dis *= r; t.position = center + dis; t.rotation *= r ;
    }
    退出移动版