3D游戏03——空间与运动

阅读: 评论:0

3D游戏03——空间与运动

3D游戏03——空间与运动

简答题

  1. 游戏对象运动的本质是什么?
  • 游戏对象运动的本质是对象的属性(如位置(position),角度(rotation),大小(scale)等)随着时间发生的变化。
  1. 请用三种方法以上方法,实现物体的抛物线运动
  • 通过Vector3.Lerp方法
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Trans : MonoBehaviour
{public float velocity = 10; //初速度public float angle = 45;  //初始角度public float gravity = -10; //重力加速度private float x;private float y;// Start is called before the first frame updatevoid Start(){x = velocity * Mathf.Cos(angle); //分量的初始速度y = velocity * Mathf.Sin(angle);}// Update is called once per framevoid Update(){Vector3 v = new Vector3(Time.deltaTime * x, Time.deltaTime * y, 0);transform.position = Vector3.Lerp(transform.position, transform.position + v, 1);y += gravity * Time.deltaTime;   }
}
  • 通过Translate方法:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;public class Trans : MonoBehaviour {public float velcocity = 10;public float angle = 45;public float gravity = -10;private float x;private float y;void Start () {x = velcocity * Mathf.Cos(angle);y = velcocity * Mathf.Sin(angle);}// Update is called once per framevoid Update () {Vector3 v = new Vector3(Time.deltaTime * x, Time.deltaTime * y, 0);ansform.Translate(v);y += gravity * Time.deltaTime;}
  • 使用Rigidbody的属性:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Trans : MonoBehaviour
{public Vector3 velocity;public Rigidbody rigid;// Start is called before the first frame updatevoid Start(){velocity = new Vector3(3, 10, 0);rigid = this.GetComponent<Rigidbody>();rigid.velocity = velocity;}// Update is called once per framevoid Update(){ }
}
  • 注意这种方法要首先把对象设置成Rigidbody
  1. 写一个程序,实现一个完整的太阳系, 其他星球围绕太阳的转速必须不一样,且不在一个法平面上。
  • 首先,在unity 3d场景中插入球体元素。调整好它们的位置和大小。
  • 插入相应的星球纹理素材,把图片拖动到球体上。注意,图片的Texture Type属性要选择 Sprite(2d and UI)
  • 编写脚本代码,为星球增加自传和公转的动作:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Move: MonoBehaviour
{// Start is called before the first frame updatevoid Start(){      }// Update is called once per framevoid Update(){GameObject.Find("sun").transform.Rotate(Vector3.up * Time.deltaTime * 5);GameObject.Find("mercury").transform., new Vector3(0.1f, 1, 0), 60 * Time.deltaTime);GameObject.Find("mercury").transform.Rotate(Vector3.up * Time.deltaTime * 1 / 58);GameObject.Find("venus").transform., new Vector3(0, 1, -0.1f), 55 * Time.deltaTime);GameObject.Find("venus").transform.Rotate(Vector3.up * Time.deltaTime * 10 / 243);GameObject.Find("earth").transform., new Vector3(0, 1, 0), 50 * Time.deltaTime);GameObject.Find("earth").transform.Rotate(Vector3.up * Time.deltaTime * 10);GameObject.Find("earth_1").transform., new Vector3(0, 1, 0), 50 * Time.deltaTime);       GameObject.Find("moon").transform.RotateAround(GameObject.Find("earth_1").transform.position, new Vector3(0, 1, 0), 250 * Time.deltaTime);GameObject.Find("moon").transform.Rotate(Vector3.up * Time.deltaTime * 10 / 27);GameObject.Find("mars").transform., new Vector3(0.2f, 1, 0), 45 * Time.deltaTime);GameObject.Find("mars").transform.Rotate(Vector3.up * Time.deltaTime * 10);GameObject.Find("jupiter").transform., new Vector3(-0.1f, 2, 0), 35 * Time.deltaTime);GameObject.Find("jupiter").transform.Rotate(Vector3.up * Time.deltaTime * 10 / 0.3f);GameObject.Find("saturn").transform., new Vector3(0, 1, 0.2f), 20 * Time.deltaTime);GameObject.Find("saturn").transform.Rotate(Vector3.up * Time.deltaTime * 10 / 0.4f);GameObject.Find("uranus").transform., new Vector3(0, 2, 0.1f), 15 * Time.deltaTime);GameObject.Find("uranus").transform.Rotate(Vector3.up * Time.deltaTime * 10 / 0.6f);GameObject.Find("neptune").transform., new Vector3(-0.1f, 1, -0.1f), 10 * Time.deltaTime);GameObject.Find("neptune").transform.Rotate(Vector3.up * Time.deltaTime * 10 / 0.7f);}
}
  • 可以从hierarchy中看到,我们添加了两个earth对象。因为moon在围绕自转的地球旋转时的动作有些异常… 查询后发现有博主做了这样的解决:设置moon按一个只公转不自传的地球副本公转,让另一个earth执行公转和自转同时进行的任务。
  • 最后再微调一下星球的位置。将背景色设置为黑色,为星球增加公转的轨迹(Add Component->Trail Renderer)和Light Point
  • 可以看到效果如下:

  • github传送门(内含演示视频)

编程实践

  • 阅读以下游戏脚本
Priests and DevilsPriests 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 oneside 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 ( .html )
  • 列出游戏中提及的事物(Objects)

牧师、恶魔、船、河岸、河

  • 用表格列出玩家动作表(规则表),注意,动作越少越好
ConditionsActionsResults
有牧师/恶魔在右岸,船停靠在右岸点击岸上牧师/恶魔牧师/恶魔上船
有牧师/恶魔在船上,船停靠在右岸点击船上牧师/恶魔牧师/恶魔上岸
船停靠在岸边点击“Go"船向对岸驶去
有牧师/恶魔在左岸,船停靠在左岸点击岸上牧师/恶魔牧师/恶魔上船
有牧师/恶魔在船上,船停靠在左岸点击船上牧师/恶魔牧师/恶魔上岸
右岸/船上/左岸 恶魔数量大于牧师数量/牧师死亡,游戏结束
  • 请将游戏中对象做成预制
  • 游戏界面如下:
  • 根据MVC架构,把程序拆分成模型(Model)、界面(View)和控制器(Controller)三个部分:
  • Model主要功能代码:
using UnityEngine;
using System.Collections;
using Com.game;public class Model : MonoBehaviour
{void Start(){GameSceneController my = GameSceneController.GetInstance();my.setBaseCode(this);}
}namespace Com.game
{//实现接口public interface IUserActions{void priest_SOnB();void priest_EOnB();void devil_SOnB();void devil_EOnB();void moveBoat();void offBoatS();void offBoatE();void restart();}public enum State { START, STOE, ETOS, END, WIN, LOSE }; //游戏的六种当前状态public class GameSceneController : System.Object, IUserActions{private static GameSceneController instance;private Model base_code;private Controller game_obj;public State state = State.START;public Model getBaseCode(){return base_code;}internal void setBaseCode(Model c){if (null == base_code){base_code = c;}}public Controller getGenGameObject(){return game_obj;}internal void setGenGameObject(Controller ggo){if (null == game_obj){game_obj = ggo;}}public void priest_SOnB(){game_obj.priestStartOnBoat();}public void priest_EOnB(){game_obj.priestEndOnBoat();}public void devil_SOnB(){game_obj.devilStartOnBoat();}public void offBoatS(){OffTheBoat(1);}public void offBoatE(){OffTheBoat(0);}public void devil_EOnB(){game_obj.devilEndOnBoat();}public void moveBoat(){veBoat();}public static GameSceneController GetInstance(){if (null == instance){instance = new GameSceneController();}return instance;}public void restart(){Application.LoadLevel(Application.loadedLevelName);state = State.START;}}
}
  • View主要功能代码:
using UnityEngine;
using System.Collections;
using Com.game;public class View : MonoBehaviour
{IUserActions act;GameSceneController my;float width, height;void Start(){my = GameSceneController.GetInstance();act = GameSceneController.GetInstance() as IUserActions;}float stw(float scale){return (Screen.width - width) / scale;}float sth(float scale){return (Screen.height - height) / scale;}void OnGUI(){width = Screen.width / 15;height = Screen.height / 15;print(my.state);if (my.state == State.WIN){if (GUI.Button(new Rect(stw(2f), sth(6f), width, height), "Your Win!")){start();}}else if (my.state == State.LOSE){if (GUI.Button(new Rect(stw(2f), sth(6f), width, height), "Your Lose!")){start();}}else{//通过接口实现动作if (my.state == State.START || my.state == State.END){if (GUI.Button(new Rect(stw(2f), sth(6f), width, height), "GO")){veBoat();}if (GUI.Button(new Rect(stw(10.5f), sth(4.5f), width, height), "ON")){act.devil_SOnB();}if (GUI.Button(new Rect(stw(4.3f), sth(4.5f), width, height), "ON")){act.priest_SOnB();}if (GUI.Button(new Rect(stw(1.1f), sth(4.5f), width, height), "ON")){act.devil_EOnB();}if (GUI.Button(new Rect(stw(1.3f), sth(4.5f), width, height), "ON")){act.priest_EOnB();}if (GUI.Button(new Rect(stw(2.5f), sth(1.2f), width, height), "OFF")){act.offBoatS();}if (GUI.Button(new Rect(stw(1.7f), sth(1.2f), width, height), "OFF")){act.offBoatE();}}}}
}
  • Controller主要功能代码:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Com.game;public class Controller : MonoBehaviour
{GameObject[] boat = new GameObject[2];GameObject boat_obj;GameSceneController my;Stack<GameObject> p_start = new Stack<GameObject>();Stack<GameObject> p_end = new Stack<GameObject>();Stack<GameObject> d_start = new Stack<GameObject>();Stack<GameObject> d_end = new Stack<GameObject>();Vector3 bankStart = new Vector3(0, 0, -12);Vector3 priestStart = new Vector3(0, 2.8f, -11f);Vector3 devilStart = new Vector3(0, 2.8f, -16f);Vector3 priestEnd = new Vector3(0, 2.8f, 8f);Vector3 devilEnd = new Vector3(0, 2.8f, 13f);Vector3 boatStart = new Vector3(0, 0, -4);Vector3 bankEnd = new Vector3(0, 0, 12);Vector3 boatEnd = new Vector3(0, 0, 4);Vector3 River = new Vector3(0, -1.6f, 0f);public float speed = 50f;void Start(){my = GameSceneController.GetInstance();my.setGenGameObject(this);Screen();}//实例化游戏对象void Screen(){Instantiate(Resources.Load("Prefabs/Bank"), bankStart, Quaternion.identity);Instantiate(Resources.Load("Prefabs/Bank"), bankEnd, Quaternion.identity);Instantiate(Resources.Load("Prefabs/River"), River, Quaternion.identity);boat_obj = Instantiate(Resources.Load("Prefabs/Boat"), boatStart, Quaternion.identity) as GameObject;for (int i = 0; i < 3; ++i){p_start.Push(Instantiate(Resources.Load("Prefabs/Priest")) as GameObject);d_start.Push(Instantiate(Resources.Load("Prefabs/Devil")) as GameObject);}}//检查游戏状态void check(){int p_on_Bank = 0, d_on_Bank = 0;int p_s = 0, d_s = 0, p_e = 0, d_e = 0;if (p_end.Count == 3 && d_end.Count == 3){my.state = State.WIN;return;}for (int i = 0; i < 2; ++i){if (boat[i] != null && boat[i].tag == "Priest")p_on_Bank++; //给牧师和恶魔添加Tag,以区分else if (boat[i] != null && boat[i].tag == "Devil")d_on_Bank++;}if (my.state == State.START){p_s = p_start.Count + p_on_Bank;d_s = d_start.Count + d_on_Bank;p_e = p_end.Count;d_e = d_end.Count;}else if (my.state == State.END){p_e = p_on_Bank + p_end.Count;d_e = d_on_Bank + d_end.Count;p_s = p_start.Count;d_s = d_start.Count;}if ((p_e < d_e && p_e != 0) || (p_s < d_s && p_s != 0)){my.state = State.LOSE;}}int boatCapacity(){int capacity = 0;for (int i = 0; i < 2; ++i){if (boat[i] == null) capacity++;}return capacity;}//动作上船void getOnBoat(GameObject obj){if (boatCapacity() != 0){ansform.parent = ansform; //把船设置为游戏角色的子对象if (boat[0] == null){boat[0] = ansform.localPosition = new Vector3(0, -0.9f, 0);}else{boat[1] = ansform.localPosition = new Vector3(0, -0.9f, 0.3f);}}}//动作开船public void moveBoat(){if (boatCapacity() != 2){if (my.state == State.START){my.state = State.STOE;}else if (my.state == State.END){my.state = State.ETOS;}}}//动作下船public void getOffTheBoat(int side){if (boat[side] != null){boat[side].transform.parent = null; //取消船和角色的父子关系if (my.state == State.END){if (boat[side].tag == "Priest"){p_end.Push(boat[side]);}else if (boat[side].tag == "Devil"){d_end.Push(boat[side]);}}else if (my.state == State.START){if (boat[side].tag == "Priest"){p_start.Push(boat[side]);}else if (boat[side].tag == "Devil"){d_start.Push(boat[side]);}}boat[side] = null;}}void set_Position(Stack<GameObject> stack, Vector3 pos){GameObject[] array = stack.ToArray();for (int i = 0; i < stack.Count; ++i){array[i].transform.position = new Vector3(pos.x, pos.y, pos.z + 1.5f * i);}}public void priestStartOnBoat(){if (my.state == State.START && p_start.Count != 0 && boatCapacity() != 0)getOnBoat(p_start.Pop());}public void devilStartOnBoat(){if (my.state == State.START && d_start.Count != 0 && boatCapacity() != 0)getOnBoat(d_start.Pop());}public void priestEndOnBoat(){if (my.state == State.END && p_end.Count != 0 && boatCapacity() != 0)getOnBoat(p_end.Pop());}public void devilEndOnBoat(){if (my.state == State.END && d_end.Count != 0 && boatCapacity() != 0)getOnBoat(d_end.Pop());}void Update(){set_Position(p_start, priestStart);set_Position(p_end, priestEnd);set_Position(d_start, devilStart);set_Position(d_end, devilEnd);if (my.state == State.STOE){ansform.position = Vector3.MoveTowards(ansform.position, boatEnd, speed * Time.deltaTime);if (ansform.position == boatEnd){my.state = State.END;}}else if (my.state == State.ETOS){ansform.position = Vector3.MoveTowards(ansform.position, boatStart, speed * Time.deltaTime);if (ansform.position == boatStart){my.state = State.START;}}else check();}
}
  • 将Controller.cs挂载到主摄像机,View.cs挂载到一个空的GameObject,就可以运行游戏了。
  • github传送门(内含游戏演示视频)

本文发布于:2024-01-27 18:55:45,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/17063529452013.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:游戏   空间
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23