hw3-空間與運動作業

簡答題

1.遊戲對象運動的本質是什麼?

遊戲對象運動的本質是遊戲對象位置和狀態的改變。通過遊戲對象transform屬性的position、rotation和scale等屬性的變化來實現運動。

2.請用三種方法以上方法,實現物體的拋物線運動。
  • 修改Transform中的position屬性直接改變位置
    拋物線運動水平方向上的移動距離爲T,豎直方向上的移動距離爲VT*T。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class methodA : MonoBehaviour {

    public int Myspeed = 2;
    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        this.transform.position += Vector3.right * Time.deltaTime;
        this.transform.position += Vector3.down * Time.deltaTime * Time.deltaTime * Myspeed;
    }
}
  • 使用向量Vector3的MoveTowards方法
    方法原型爲:
static function MoveTowards (current : Vector3, target : Vector3, maxDistanceDelta : float) : Vector3 

物體每一幀都在水平方向和豎直方向移動,與方法1同理。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class methodB : MonoBehaviour {
    Vector3 target1 = Vector3.right * 5;
    Vector3 target2 = Vector3.down * 5;
    float speed1 = 1;
    float speed2 = 2;
    
    // Update is called once per frame
    void Update(){
        float step1 = speed1 * Time.deltaTime;
        float step2 = speed2 * Time.deltaTime * Time.deltaTime;
        transform.position = Vector3.MoveTowards(transform.position, target1, step1);
        transform.position = Vector3.MoveTowards(transform.position, target2, step2);
    }
}
  • 使用向量Vector3的Lerp方法
    方法原型爲:
static function Lerp (from : Vector3, to : Vector3, t : float) : Vector3

按照數字t在from到to之間插值。t大小在 [0…1]之間,當t = 0時,返回from,當t = 1時,返回to。當t = 0.5 返回from和to的平均數。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class methodC : MonoBehaviour {
    public float Speed = 0.5f;
    Vector3 Target1 = new Vector3(-6, -3, 8);
    //控制物體向Target移動
    void Update()
    {
        gameObject.transform.localPosition = Vector3.Lerp(transform.position, Target1, Speed * Time.deltaTime);
    }
}
3.寫一個程序,實現一個完整的太陽系, 其他星球圍繞太陽的轉速必須不一樣,且不在一個法平面上。
  • 設計思路
    (1) 首先設置10個球體,分別是太陽、八大行星和月球。八大行星按照離太陽的距離從近到遠依次爲水星、金星、地球、火星、木星、土星、天王星、海王星。
    在這裏插入圖片描述
    (2)設置天體的自轉和公轉,包括地月系。由於題目需要行星要在不同的法平面旋轉,我們隨機設定行星旋轉的軸位置,並且設置旋轉速度的不同。以天王星的自轉和公轉爲例。
    自轉:public void Rotate(Vector3 eulers,Space relativeTo)
    公轉:public void RotateAround(Vector3 point,Vector3 axis,float angle)
    代碼如下:
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class tianwang : MonoBehaviour {
        public Transform Sun;
        public float rotationSpeed = 2;
        public float speed = 8.5f;
        private float rx;
        private float ry;
        private float rz;
        // Use this for initialization
        void Start()
        {
            rx = Random.Range(10, 30);
            ry = Random.Range(40, 60);
            rz = Random.Range(10, 30);
        }
    
        // Update is called once per frame
        void Update()
        {
            Vector3 axis = new Vector3(rx, ry, rz);
            this.transform.RotateAround(Sun.position, axis, speed * Time.deltaTime);
            transform.Rotate(Vector3.down * rotationSpeed, Space.World);
        }
    }
    
    (3)設置攝像機在PLAY過程中也可以移動來觀察天體運動。
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class View : MonoBehaviour {
        public float sensitivityMouse = 2f;
        public float sensitivetyKeyBoard = 0.1f;
        public float sensitivetyMouseWheel = 10f;
    
        // Use this for initialization
        void Start()
        {
    
        }
    
        // Update is called once per frame
        void Update()
        {
            //按着鼠標右鍵實現視角轉動  
            if (Input.GetMouseButton(1))
            {
                transform.Rotate(-Input.GetAxis("Mouse Y") * sensitivityMouse, Input.GetAxis("Mouse X") * sensitivityMouse, 0);
            }
    
            //鍵盤按鈕←/a和→/d實現視角水平移動,鍵盤按鈕↑/w和↓/s實現視角水平旋轉  
            if (Input.GetAxis("Horizontal") != 0)
            {
                transform.Translate(Input.GetAxis("Horizontal") * sensitivetyKeyBoard, 0, 0);
            }
            if (Input.GetAxis("Vertical") != 0)
            {
                transform.Translate(0, Input.GetAxis("Vertical") * sensitivetyKeyBoard, 0);
            }
        }
    
    }
    
  • 實現效果
    我的GitHub

編程實踐

【閱讀以下游戲腳本】

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/game/2535/priests-and-devils.html )
  • 列出遊戲中提及的事物(Objects)
  • 用表格列出玩家動作表(規則表),注意,動作越少越好
  • 請將遊戲中對象做成預製
  • 在 GenGameObjects 中創建 長方形、正方形、球 及其色彩代表遊戲中的對象。
  • 使用 C# 集合類型 有效組織對象
  • 整個遊戲僅 主攝像機 和 一個 Empty 對象, 其他對象必須代碼動態生成!!! 。 整個遊戲不許出現 Find 遊戲對象, SendMessage 這類突破程序結構的 通訊耦合 語句。 違背本條準則,不給分
  • 請使用課件架構圖編程,不接受非 MVC 結構程序
  • 注意細節,例如:船未靠岸,牧師與魔鬼上下船運動中,均不能接受用戶事件!

【遊戲中提及的對象】
牧師,魔鬼,小船,小河,河岸
【玩家動作表】

動作 條件 結果
點擊岸上的人 岸上有人,船上有空位 人進入船,岸上人數減少
點擊船 船上有人 船移動到對岸
點擊船上的人 船上有人 人上岸,船上人數減少

【MVC架構圖】
在這裏插入圖片描述
【實現】


  • Director
    Director是最高層的控制器,運行遊戲時始終只有一個實例,它掌控着場景的加載、切換等,也可以控制遊戲暫停、結束等等。
public class SSDirector : System.Object {
    private static SSDirector Myinstance;
    public SceneController FirstController { get; set; }

    public static SSDirector getInstance() {
        if (Myinstance == null) {
            Myinstance = new Director ();
        }
        return Myinstance;
    }
}
  • SceneController接口
    SceneController 是導演控制場景控制器的渠道。在上面的 SSDirector 類中,FirstController 就是SceneController的實現。
public interface SceneController {
    void loadResources ();
}
  • Moveable類
    掛載在GameOject上實現遊戲對象的運動。
  • CharacterController類
    對遊戲角色進行封裝,在構造函數中動態實例化了一個perfab,創建GameObject。另外實現了對遊戲角色狀態和行爲的控制函數。

(1)實例化預製對象(以Priest爲例)

character = Object.Instantiate(Resources.Load("Priest", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;

(2)角色狀態和行爲設置

public void setname(string name)  //設置對象名稱
public void setPosition(Vector3 pos)  //設置對象位置
public void moveToPosition(Vector3 dest)  //設置對象移動
public int getType()  //返回對象角色
public string getName()  //返回對象名稱
public void getOnBoat()  //上船
public void getOnCoast()  //上岸
public bool isOnBoat()  //判斷是否在船上
  • BoatController類
    封裝了船類,提供getEmptyPosition()方法,給出自己的空位,讓遊戲角色能夠移動到合適的位置。

(1)預製船和設置起始狀態

 from_positions = new Vector3[] { new Vector3(4.5F, 1.5F, 0), new Vector3(5.5F, 1.5F, 0) };
        to_positions = new Vector3[] { new Vector3(-5.5F, 1.5F, 0), new Vector3(-4.5F, 1.5F, 0) };

        boat = Object.Instantiate(Resources.Load("Boat", typeof(GameObject)), fromPosition, Quaternion.identity, null) as GameObject;
        boat.name = "boat";

(2)設置船的行爲

public void Move()  //船的移動
public  Vector3 getEmptyPosition()   //得到船上的孔偉
public bool isEmpty()  //判斷船是否爲空
public void GetOnBoat(CharacterController chCtrl)  //調用船的上船狀態
  • CoastController類
    封裝了河岸,具體內容和BoatController類相同。
  • UserAction接口
    FirstController必須要實現這個接口才能對用戶的輸入做出反應。在ClickGUI和UserGUI這兩個類中,都保存了一個UserAction的引用。當ClickGUI監測到用戶點擊GameObject的時候,就會調用這個引用的characterIsClicked方法,這樣FirstController就知道哪一個遊戲角色被點擊了。UserGUI同理,它監測的是“用戶點擊Restart按鈕”的事件。
public interface UserAction {
   void moveBoat();
   void characterIsClicked(CharacterController characterCtrl);
   void restart();
}
  • ClickGUI類
    lickGUI類是用來監測用戶點擊,並調用SceneController進行響應的。
public class ClickGUI : MonoBehaviour {
   UserAction action;
   CharacterController characterController;

   public void setController(CharacterController characterCtrl) {
       characterController = characterCtrl;
   }

   void Start() {
       action = Director.getInstance ().FirstController as UserAction;
   }

   void OnMouseDown() {
       if (gameObject.name == "boat") {
           action.moveBoat ();
       } else {
           action.characterIsClicked (characterController);
       }
   }
}

【遊戲展示視頻】
我的Github

【參考博客】

https://blog.csdn.net/yaoxh6/article/details/79773632

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章