Unity 小社課

第四、五堂 By: 貝絲

這堂課你們會學到...

Sprite & sprite renderer

  • Sprite : 精靈
  • 一種 2D 圖像資源
  • 用來表示角色、背景、物品等物件的視覺效果
  • 因為這樣的圖像並不是背景的一部分,而是「懸浮」在背景之上,向幽靈、精靈一樣,所以叫做「精靈圖」

sprite 是什麼?

  • 精靈圖渲染器
  • 綁定在 Game Object (Sprite) 上面的 Component
  • 會渲染 Sprite 並控制他在場景中的視覺效果

sprite renderer 是什麼?

渲染對象

渲染後疊加於 Sprite 上的顏色

x、y 軸鏡像翻轉

渲染材質

繪製模式

Sprite 的排序圖層,控制渲染時的優先順序

Sprite 在圖層中的渲染優先順序,數字較低的會先被渲染,數字高的蓋過數字低的

draw mode

只能依原比例調整大小、位子

可以依照自己的喜好調整長寬

把圖片像磁磚一樣重複排出

丟一張圖片到你的 assets 裡面並點開

我現在以這隻鹿為例

圖像 Assets 設置

點他

圖像 Assets 設置

圖像類型

類似比例尺,初始值為100,圖片大小縮放為100/數字(ex: 數字50代表放大成兩倍

物體的定位點

圖片過濾模式:Bilinear平滑(模糊)、Point 像素

可以改變圖片的旋轉中心、拉伸限制

改完記得按套用

一般會用 Tight (節省效能)

如果有改 Draw Mode 的話(Sliced、Tiled)要改成 Full Rect

Transform

  • 一個 Component
  • 儲存 Game Object 在場景座標中的位置、旋轉、尺寸比例
  • Position(位置):物件的位置,x: 左右、y: 上下、z: 前後
    • 2D 遊戲中除了 Camera的z會在-10之外其他都會是0(不然可能會照不到)
  • Rotation(旋轉):物件在三個座標軸上的旋轉角度
    • 2D 通常只會用到 z 軸
  • Scale(比例)物件在三個座標軸上的尺寸比例
    • 大於1:放大、0~1:縮小、小於0:鏡像
  • 所有 Transform 都是用 Vector3(三維向量)的資料型態在腳本中儲存和使用

transform 

C# 基本概念

  • Field(藍色方塊):用來儲存資料 ex: 玩家生命力、攻擊力、移動速度...
    • 最常用的:
      • int:預設值為0
      • float(數字後面要加f):預設值為0
      • bool:預設值為 false
      • string:預設值為null(什麼都沒有)
      • 變數在預設下都是 private
  • Property(白色板手):讓外部讀取、覆寫這些資料 ex: 敵人的血量
  • Method(紫色方塊):操作資料、進行複雜變化、重複使用

腳本的架構

  • 程式的藍圖
  • Field, Property, Method 的主人
  • 呼叫 class:new + class名稱+();
    • new:代表創造一個新的object(物件)
    • object:一個 class 的複製體
      • 加上".":出現class中有 public 關鍵字的 field, property, method的清單
      • 每個 object 都是獨立個體,有自己獨立的資料
  • constructor:建構一個 class
    • 預設:public + class 名稱 + () + {}

Class

Deer.cs

Class 舉例

using System.Collections;
using System.Collections.Generic;
using UnityEngine; // 有這行才能用Debug.log


public class Deer {
	//field: 儲存變數的地方
    public string name = "Deer";
    public int age = 16;
    float weight = 120.5f;
    bool isDead = false;
    //constructor
    public Deer() {
        Debug.Log("我好可愛");
    }
}
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEngine;

public class deerManager : MonoBehaviour
{
    
    void Start()
    {
       new Deer();
    }
}

deerManager.cs

  • 內部改變
    • 到 class 進行修改
    • 會影響到所有創造出來的 object
  • 外部改變
    • 對每個不同的 object 單獨調整

改寫資料

  • 可以讓我們隨時知道object的位子和狀態
  • 可以對這些資料進行操作

存取 object

using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using UnityEngine;

public class deerManager : MonoBehaviour
{
    //Field (儲存資料的地方)
    Deer deer1; // 特殊資料種類
    //Deer: 儲存類型
    //deer: 自行命名的變數
    Deer deer2;
    void Start()
    {
        deer1 = new Deer(); //創造一個 "Deer object",並把這個object存在 "deer"這個變數中
        deer1.name = "Bob";
        deer1.age = 8;
        deer2 = new Deer();
        deer2.name = "Paul";
        deer2.age = 10;
    }
}
  • public + 資料種類 + 變數名稱 + {get; set;} + "=" + 初始值
  • get: 只能被讀取(可以知道值為何,但無法改變)
  • set: 複寫

property

// Deer.cs
public class Deer {
    public string name = "Deer";
    public int age = 16;
    public int level {get;} = 1;   
}

// deerManager.cs 
using UnityEngine;
public class deerManager : MonoBehaviour
{
    Deer deer1; 
    void Start() {
        deer1 = new Deer(); 
        Debug.Log("這隻鹿的等級(?)為 " + deer1.level);
        //Console 視窗:這隻鹿的等級(?)為 1     
    }
}
//Deer.cs
public class Deer {
    public string name = "Deer";
    public int age = 16;
    public int level {get;set;} = 1;
}

//deerManager.cs
public class deerManager : MonoBehaviour
{
    Deer deer1; 
    void Start()
    {
        deer1 = new Deer(); 
        deer1.level = 2;
    }
}
  • get return
    • 使原本的變數成為中間人,只負責傳遞變數
    • 可讓原本的變數成為 private
  • set value
    • 透過 property 去覆寫一個變數

property

// Deer.cs
public class Deer {
    string name = "Bob";
    public string Name {get {return name;} } 
    
}

// deerManager.cs 
using UnityEngine;
public class deerManager : MonoBehaviour
{
    Deer deer1; 
    void Start()
    {
        deer1 = new Deer();
        Debug.Log(deer1.Name);
        //Console 視窗:Bob
        
    }
}
//Deer.cs
public class Deer {
	string name = "Bob";
    public string Name {get {return name;} set {name = value;} } 
    
}

//deerManager.cs
public class deerManager : MonoBehaviour
{ 
    Deer deer1;
    void Start()
    {
        deer1 = new Deer(); 
        deer1.Name = "Paul";
    }
}
  • 對資料操作
  • 進行複雜的變化
  • private/public + 回傳資料種類 + 名稱 + () + {}
  • void:不回傳任何訊息
  • 呼叫 method:method名稱+ () + ";"

Method

//Deer.cs
public class Deer {

    public void Move() {
        Debug.Log ("我動了");
        string newLocation = GetLocation();
        Debug.Log("我移動到了" + newLocation);
        //void: 不回傳值
    }
    
    private string GetLocation() {
        string location = "貝絲家";
        return location;
        //method 名稱前的 "string": 回傳字串
        //return: 回傳+離開 method
        
    }
    
    public void getGift(string gift) {
        Debug.Log ("我得到了"+ gift);
        //gift: 參數
    }
    
    public void Test(string test, int number, float score) {
        //也可以在 method 裡面設定很多個參數
    }
 
}
//deerManager.cs
public class deerManager : MonoBehaviour {
    Deer deer1; 
    
    void Start()
    {
        deer1 = new Deer();
        deer1.Move(); 
        //Console視窗:我移動了&我移動到了貝絲家
        deer1.getGift("禮物"); 
        //Console視窗:我得到了禮物

    }
}
  • 全域變數:
    • 不管在哪裡使用電腦都找得到
  • 區域變數:
    • 只存在於他被宣告的 method 中
    • 只能在他被宣告的 method 裡使用
    • 不用寫 public / private

全域變數 v.s. 區域變數

public class Deer {
    string name = "Bob"; //name為全域變數
 
    private string GetLocation() {
        string location = "貝絲家"; //location為區域變數
        return location; 
    }
}

array & Dictionary & List

  • 宣告:資料種類 + [] + 自行命名的名稱
  • 創造陣列:變數名稱 = new  資料種類[陣列大小];
  • 剩下的賦值、應用都跟c++一樣
  • 陣列也是一個object

陣列

public class deerManager : MonoBehaviour
{
    Deer[] deers; //宣告
    void Start()
    {
        deers = new Deer[10]; //創造一個Deer陣列
        deers[0] = new Deer(); //如果陣列是 game object 的陣列,則需要先指派一個物件
        deers[0].Name = "Paul";
        deers[0].Move();
        deers[1].getGift("草"); //因為沒有宣告所以不會成功執行
    }
}
  • 要使用 List 和 Dictionary 的話最前面要加上
    using System.Collections.Generic

注意

  • 宣告:List<資料種類> 名稱
    • <>:泛型(Generic),代表宣告時需賦予資料種類才能完成
  • 創造 List:變數名稱 = new List<資料種類>();
  • 加入物件:list名稱.Add(物件);

list

using System.Collections.Generic;
public class deerManager : MonoBehaviour
{
    List<Deer> deerList; //宣告
    void Start()
    {
        deerList = new List<Deer>(); //創造一個 list
        for (int i = 0; i < 10; i++) {
            deerList.Add(new Deer()); //加入10個 Deer 物件到 list 中
        }
        deerList[0].age = 10;
        deerList[1].Name = "Robert";
        //上面兩行是跟陣列一樣的用法

    }
}
  • 宣告:Dictionary<key, value> 名稱
    • key 跟 value 放的都是資料種類
    • key:編號
    • value:存放的資料類型
  • 創造 List:變數名稱 = new Dictionary<資料種類>();
  • 加入物件:dictionary名稱.Add(編號,物件);

Dictionary

using System.Collections.Generic;

public class deerManager : MonoBehaviour
{
    Dictionary<string, Deer> deerByName; //宣告
    void Start()
    {
        deerByName = new Dictionary<string, Deer>(); //創造一個 Dictionary
        deerByName.Add("Bob", new Deer());
        deerByName.Add("Paul", new Deer());
        deerByName["Bob"].age = 8; //用法跟陣列也很像,只不過直接指定 key
        deerByName["Paul"].age = 10;
    }
}
  • .Count:回傳 int,代表存放了多少資料
  • .Clear:清空
  • .Contains:回傳 bool,尋找資料是否存在
  • .Remove:移除一份資料

常用的 method&property

Vector2、Vector3

vector2、vector3、transform

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

public class deerManager : MonoBehaviour
{
    Vector2 vec2a, vec2b, vec2c;
    Vector3 vec3a, vec3b, vec3c;
    float exampleFloat;
    void Start()
    {
        //賦值
        vec2a = Vector2.up; //(0,1)
        vec2b = Vector2.right; //(1,0)
        vec3a = Vector3.forward; //(0,0,1)
        vec3b.Set(0,0,0); //直接設定Vector的值
        vec3b = new Vector3(25.0f, 20, 31);
        //運算
        vec2c = vec2a + vec2b; //(1,1) = (x1+x2, y1+y2)
        vec2c = vec2c * 10; //(10,10) = (k * x1, k * x2)
        vec2c *= 10; //同上

        exampleFloat = Vector2.Distance(vec2a,vec2b);
        exampleFloat = Vector2.Angle(vec2a, vec2b); //回傳起始&結束座標連線和水平方向的夾角
        exampleFloat = vec2a.magnitude; //回傳向量長度
        transform.position = Vector2.MoveTowards(transform.position, vec2c, 0.01f); 
        //(起點vector, 終點vector, 每次執行的移動距離(移動速度)) -> 寫在Update/FixedUpdate可以讓物件不斷向目標vector前進
        transform.position = Vector2.Lerp(transform.position, vec2c, 0.01f);
        //(起點vector, 終點vector, 兩個vector的差值) -> 更加平滑的移動(分點公式的兩線段比例)
        exampleFloat = vec3a.x;
        exampleFloat = vec3a.y;
        exampleFloat = vec3a.z; //Vector3 獨有

        transform.position = new Vector3(1, 0, 1);
        float x = transform.position.x;
        transform.localPosition = Vector3.zero; //相對於父物件的位置
        transform.Scale = Vector3.one; //GameObject於三維座標上的尺寸比例
        transform.localScale = new Vector3(-transform.localScale.x,transform.localScale.y,transform.localScale.z); //左右旋轉
        transform.rotation = Quaternion.identity; //GameObject的旋轉,以Quaternion(四元數)格式儲存,非常複雜,此處的identity為不旋轉
        transform.rotation = Quaternion.Euler(95,10,31); //以三維方式(歐拉角)旋轉
        transform.Translate(new Vector3(12, 15, 1)); //將position以一定的向量變動


    }
}

其他小東西

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

public class deerManager : MonoBehaviour
{
    Vector2 vec2a, vec2b, vec2c;
    Vector3 vec3a, vec3b, vec3c;
    float exampleFloat;
    void Start()
    {
    	float exampleFloat = 2.5f;
        float exampleFloatAbs = Mathf.Abs(exampleFloat); //絕對值
 
        SpriteRenderer exampleSpriteRenderer = GetComponent<SpriteRenderer>();
 
        GameObject exampleObject1 = GameObject.Find("cat"); //用名字找Scene中的遊戲物件並回傳第一個符合的
        GameObject exampleObject2 = GameObject.FindGameObjectWithTag("Cat"); //用Tag找Scene中的遊戲物件並回傳第一個符合的
        GameObject.Destroy(this.gameObject); //摧毀以此Script作為Component的遊戲物件
        exampleSpriteRenderer.enabled = true; //exampleSpriteRenderer的啟用狀態,可直接修改(相當於框框打勾與否)
        this.enabled = true; //此Script的啟用狀態,相當於框框打勾與否
        exampleObject2.SetActive(false); //停用exampleObject2(相當於框框不打勾)
        float DeltaTime = Time.deltaTime; //在FixedUpdate中,這個值大約為0.02秒,其他地方則為一幀的時間
    }
}

Unity小社課 第四、五堂

By d11230618陳子毓

Unity小社課 第四、五堂

  • 186