Get Started with Unity3D - 2

简答 & 程序验证

简答题仓库地址

注意:本简答题作业所有代码/实现/实验均包含在SolarSystem项目中,由不同的场景呈现,通过选择不同的场景,您可以快速查看各题目实现效果

  • 游戏对象运动的本质是什么?

    是游戏对象的位置属性在每个时刻的变化。

    1
    2
    3
    4
    5
    // 示例代码:沿y轴向上匀速运动
    // 打开项目文件夹下Object Motion以查看完整代码
    void Update () {
    this.transform.position += Vector3.up * Time.deltaTime;
    }
  • 请用三种方法以上方法,实现物体的抛物线运动。(在Parabola文件夹下三个场景分别对应三种方法的实现)

    1. 直接对 Transform.position 赋值

      简单来说,每一帧通过获取间隔时间Time.deltaTime,来根据抛物线函数计算下一帧物体的位置,将其赋值给Transform.position,由此达成物体的抛物线运动。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      public class parabola1 : MonoBehaviour {

      static private float g = 2.38F;
      private float speedx;
      private float speedy;
      private float x;
      private float y;

      // Use this for initialization
      void Start () {
      speedx = 1.5F;
      speedy = 4;
      }

      // Update is called once per frame
      void Update () {
      float newSpeedy = speedy - g * Time.deltaTime;
      x = this.transform.position.x + speedx * Time.deltaTime;
      y = (speedy + newSpeedy) / 2 * Time.deltaTime + this.transform.position.y;
      if (y <= 0) {
      y = -y;
      newSpeedy = -newSpeedy;
      }
      speedy = newSpeedy;
      this.transform.position = new Vector3(
      x, y, 0.0F
      );
      }
      }
    2. 通过 Rigidbody 借由物理引擎实现

      Rigidbody(刚体)组件可以让对象受Unity3D的物理引擎控制。因而,在开启重力影响后,赋予物体初速度,就可以看到抛物线运动的效果。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      [RequireComponent(typeof(Rigidbody))]
      public class Parabola2 : MonoBehaviour {

      private Rigidbody rigidbody;
      private Vector3 initSpeed;

      // Use this for initialization
      void Start () {
      rigidbody = this.GetComponent<Rigidbody> ();
      initSpeed = new Vector3 (3, 10, 0);
      rigidbody.velocity = initSpeed;
      }

      // Update is called once per frame
      void Update () {

      }
      }
    3. 通过 CharacterController 通过函数实现

      CharacterController(角色控制器)是用于第一人称/第三人称角色的碰撞模型,免去了繁琐的刚体设置,并提供了Simple Move和Move两种方法,因为Simple Move会屏蔽y方向速度,因此此处使用Move并结合函数计算速度方向来实现抛物线运动。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      [RequireComponent(typeof(CharacterController))]
      public class Parabola3 : MonoBehaviour {

      private CharacterController charactercontroller;
      private Vector3 speed;

      // Use this for initialization
      void Start () {
      charactercontroller = this.GetComponent<CharacterController> ();
      speed = new Vector3 (2, 5, 0);
      }

      // Update is called once per frame
      void Update () {
      speed -= 3.0F * Time.deltaTime * Vector3.up;
      charactercontroller.Move (speed * Time.deltaTime);
      }
      }
  • 写一个程序,实现一个完整的太阳系, 其他星球围绕太阳的转速必须不一样,且不在一个法平面上。

    既然要做太阳系,为了较为真实,自然要用到太阳系的数据~

    | 星球名 | 半径(公里) | 轨道半径(千万公里) | 自转周期(天) | 公转周期(天) |
    | - | - | - | - | - | - |
    | 太阳 Sun |696000|0|26.9|0|
    | 水星 Mercury | 2439 | 57.9 | 58.65 | 87.70 |
    | 金星 Venus | 6052 | 108.2 | 243.01 | 224.70 |
    | 地球 Earth | 6378 | 149.6 | 0.9973 | 365.26 |
    | 火星 Mars | 3398 | 227.9 | 1.0260 | 686.98 |
    | 木星 Jupiter | 71398 | 778.3 | 0.410 | 4332.71 |
    | 土星 Saturn | 60330 | 1427.0 | 0.426 | 10759.5 |
    | 天王星 Uranus | 25400 | 2882.3 | 0.646 | 30685 |
    | 海王星 Neptune | 24600 | 4523.9 | 0.658 | 60190 |
    | 冥王星 Pluto | 1500 | 5917.1 | 6.39 | 90800 |

    不过,这些数据过于庞大,经过一些奇妙的处理(归一化)之后使用会更加好看。不过不管表面上的东西怎么变,核心代码始终是不变的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class SolarSystem : MonoBehaviour {

    public Transform Sun;
    public Transform Mercury;
    public Transform Venus;
    public Transform Earth;
    public Transform Moon;
    public Transform Mars;
    public Transform Jupiter;
    public Transform Saturn;
    public Transform Uranus;
    public Transform Neptune;
    public Transform Pluto;
    private float speed = 5;

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {
    Sun.Rotate (speed * Vector3.up * 360 * Time.deltaTime / 30);
    Mercury.Rotate (speed * Vector3.up * 360 * Time.deltaTime / 30);
    Venus.Rotate (speed * Vector3.up * 360 * Time.deltaTime / 80);
    Earth.Rotate (speed * Vector3.up * 360 * Time.deltaTime / 20);
    Moon.Rotate (speed * Vector3.up * 360 * Time.deltaTime / 30);
    Mars.Rotate (speed * Vector3.up * 360 * Time.deltaTime / 20);
    Jupiter.Rotate (speed * Vector3.up * 360 * Time.deltaTime / 10);
    Saturn.Rotate (speed * Vector3.up * 360 * Time.deltaTime / 10);
    Uranus.Rotate (speed * Vector3.up * 360 * Time.deltaTime / 10);
    Neptune.Rotate (speed * Vector3.up * 360 * Time.deltaTime / 10);
    Pluto.Rotate (speed * Vector3.up * 360 * Time.deltaTime / 15);
    // 这部分指定了自转速度

    Mercury.RotateAround (Sun.transform.position, Vector3.up + 0.1F * Vector3.left, speed * 360 * Time.deltaTime / 87);
    Venus.RotateAround (Sun.transform.position, Vector3.up - 0.05F * Vector3.left, speed * 360 * Time.deltaTime / 224);
    Earth.RotateAround (Sun.transform.position, Vector3.up + 0.13F * Vector3.left, speed * 360 * Time.deltaTime / 365);
    Moon.RotateAround (Earth.transform.position, Vector3.up + 0.2F * Vector3.left, speed * 360 * Time.deltaTime / 30);
    Mars.RotateAround (Sun.transform.position, Vector3.up - 0.18F * Vector3.left, speed * 360 * Time.deltaTime / 687);
    Jupiter.RotateAround (Sun.transform.position, Vector3.up + 0.09F * Vector3.left, speed * 360 * Time.deltaTime / 1000);
    Saturn.RotateAround (Sun.transform.position, Vector3.up - 0.21F * Vector3.left, speed * 360 * Time.deltaTime / 1300);
    Uranus.RotateAround (Sun.transform.position, Vector3.up + 0.1F * Vector3.left, speed * 360 * Time.deltaTime / 1500);
    Neptune.RotateAround (Sun.transform.position, Vector3.up + 0.2F * Vector3.left, speed * 360 * Time.deltaTime / 1800);
    Pluto.RotateAround (Sun.transform.position, Vector3.up + 0.15F * Vector3.left, speed * 360 * Time.deltaTime / 2000);
    // 这部分指定了公转轨道,因为第二个参数是法向量,因此改变该参数即可实现轨道不在同一平面内
    }
    }

    值得一提的是,为了星球的运动轨迹更加容易分辨,我们推荐您使用Trail Renderer来绘制轨迹

    效果预览:

    预览图1 - 星系全览 预览图2 - 光效展示 预览图3 - 贴图展示 预览图4 - 运动轨迹

实验:牧师与恶魔

仓库地址

参考实现

预览图

  • 列出游戏中提及的事物(Objects)

    • 船(Boat)
    • 码头(Coast)
    • 牧师(Priest)
    • 恶魔(Devil)
  • 用表格列出玩家动作表(规则表),注意,动作越少越好

    动作 结果
    点击魔鬼 若船在同一侧,且有空位,则上船。若在船上,则下船
    点击牧师 若船在同一侧,且有空位,则上船。若在船上,则下船
    点击船 若船上有至少一个牧师或魔鬼,则船移动到另一侧
    点击Restart按钮 重新开始游戏
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×