3D游戏编程与设计作业三

    科技2022-07-12  123

    目录

    1.简答并用程序验证2. 编程实践——Priests and Devils3.思考题


    1.简答并用程序验证

    (1) 游戏对象运动的本质是什么? 游戏对象运动是游戏对象按照预设好的方式向某个方向、或者围绕某个物体进行运动,其本质是相对于原点坐标的位置的变化,体现在unity中就是transform中position的各个值的改变。

    (2)请用三种方法以上方法,实现物体的抛物线运动。 a.创建一个新的vector3属性

    using System.Collections; using System.Collections.Generic; using UnityEngine; public class move1 : MonoBehaviour { int speed; // Start is called before the first frame update void Start() { speed = 1; } // Update is called once per frame void Update() { float x = this.transform.position.x; float newX = x + speed*Time.deltaTime; this.transform.position = new Vector3(newX, newX*(newX-4)); } }

    效果如下: b.直接修改position 由于抛体运动在水平方向上做匀速运动,在竖直方向上做匀加速运动,因此可以将其分解为这两个方向上的运动,然后再进行合成。

    using System.Collections; using System.Collections.Generic; using UnityEngine; public class move2 : MonoBehaviour { int speedx; int speedy; // Start is called before the first frame update void Start() { speedx = 1; speedy = -2; } // Update is called once per frame void Update() { this.transform.position += Vector3.right*speedx; this.transform.position += Vector3.up*speedy; speedy++; } }

    这种方式理论上可以实现抛体运动,但是由于Update函数的执行频率太高了,因此效果不明显,看到的就是物体一下就飞到很远的地方去了,因此就不放图了。

    c.使用translate方法

    using System.Collections; using System.Collections.Generic; using UnityEngine; public class move3 : MonoBehaviour { int speedx; int speedy; // Start is called before the first frame update void Start() { speedx = 1; speedy = -2; } // Update is called once per frame void Update() { Vector3 move = new Vector3(Time.deltaTime*speedx, Time.deltaTime*speedy, 0); speedy++; transform.Translate(move); } }

    其实和上一种方法十分类似,也是会因为update执行过快而无法看到效果。 代码传送门:GitHub

    (3)写一个程序,实现一个完整的太阳系, 其他星球围绕太阳的转速必须不一样,且不在一个法平面上。 公转代码如下:

    using System.Collections; using System.Collections.Generic; using UnityEngine; public class revolution : MonoBehaviour { public Transform center; public float speed; public float x, y, z; // Start is called before the first frame update void Start() { x = Random.Range(20, 100); y = Random.Range(20, 100); z = Random.Range(20, 100); speed = Random.Range(8, 25); } // Update is called once per frame void Update() { this.transform.RotateAround(center.position, new Vector3(x,y,0), speed*Time.deltaTime); } }

    可见使用了random函数来随机赋予法平面的角度(经过试验发现z=0效果较好)和公转速度,编写好脚本之后只需将其依次拉入已经创建好的“行星”,然后将center设为sun即可。 公转可以使用trail render特效来描绘出轨迹,利于观察,具体可参考博客介绍 效果:

    自转代码:

    using System.Collections; using System.Collections.Generic; using UnityEngine; public class rotation : MonoBehaviour { public int speed; // Start is called before the first frame update void Start() { speed = Random.Range(4, 10); } // Update is called once per frame void Update() { this.transform.RotateAround(this.transform.position, Vector3.up, speed*Time.deltaTime); } }

    然后将自转代码拖到各个行星上即可。

    但是此时发现背景太空了,因此还要给“模拟太阳系”添加一个背景图。 创建一个新的material,在shader属性中选Skybox/Panoramic,然后把自己想要的背景图片加上去: 然后在camera的add component中rendering添加skybox,在customer skybox中选择刚刚创建的background即可。 最终效果: 源代码传送门:Github

    2. 编程实践——Priests and Devils

    (1)列出游戏中提及的事物(Objects) 牧师、魔鬼、船、河岸、河

    (2)用表格列出玩家动作表(规则表),注意,动作越少越好

    角色动作牧师/魔鬼点击岸上的牧师/魔鬼,如果船当前在该角色的岸边且船上人数少于2则上船牧师/魔鬼点击船上的牧师/魔鬼,则牧师/魔鬼从船上转移到岸上船行驶到另一侧的河岸

    (3)将游戏对象做成预设 (4)在场景控制器 LoadResources 方法中加载并初始化 长方形、正方形、球 及其色彩代表游戏中的对象。

    public void LoadResources(){ Debug.Log("DD"); GameObject water = Instantiate(Resources.Load("Prefabs/Water", typeof(GameObject)), new Vector3(0,-1,0), Quaternion.identity) as GameObject; water.name = "water"; start_land = new LandModel("start"); end_land = new LandModel("end"); boat = new BoatModel(); role = new RoleModel[6]; for (int i = 0; i < 3; i++){ RoleModel r = new RoleModel("priest"); r.SetName("priest" + i); r.SetPosition(start_land.GetEmptyPosition()); r.GoLand(start_land); start_land.AddRole(r); role[i] = r; } for (int i = 3; i < 6; i++){ RoleModel r = new RoleModel("devil"); r.SetName("devil" + i); r.SetPosition(start_land.GetEmptyPosition()); r.GoLand(start_land); start_land.AddRole(r); role[i] = r; } }

    (5)使用 C# 集合类型 有效组织对象。整个游戏仅主摄像机和一个 Empty 对象, 其他对象必须代码动态生成!

    (6)请使用课件架构图编程,不接受非 MVC 结构程序 M(Model):ModelController,其中实现了boat、land、role的各个函数。 V(View):UserGUI中实现了一个简易GUI。 C(Controller):SSDirector是创建导演,一个游戏只有一个;Controller是管理各个model之间的行为的类; 除此之外,Click是相应鼠标点击的类,InterfaceController是为了降低各个类的耦合而制作的接口,用于各个model之间的调用。

    运行时只需要将controller拖入创建的空对象中即可。

    源代码传送门:GitHub

    最终效果: 获胜: 失败:

    参考 https://blog.csdn.net/TempterCyn/article/details/101110379 由于我自己写的游戏最后还是有许多bug没有解决,最终是跟着这个师兄的思路完成的。 https://www.jianshu.com/p/07028b3da573 除此之外还有很多其他博客也给我提供了帮助,地址没有一一保存了。

    3.思考题

    使用向量与变换,实现并扩展 Tranform 提供的方法,如 Rotate、RotateAround 等。 Rotate:

    void Rotate(Transform t,Vector3 axis,float angle){ var rot=Quaternion.AngleAxis(angle,axis); t.rotation*=rot; }

    RotateAround:

    void RotateAround(Transform t,Vector3 center,Vector axis,float angle){ var rot=Quaternion.AngleAxis(angle,axis); t.position=(center+(t.position-center)*rot); t.rotation=t.rotation*rot; }(这里会报错?说position不能与rotation运算?)
    Processed: 0.009, SQL: 8