可以抓半成品 ggg.zip 練習檔案繼續練習
ggg.zip | |
File Size: | 10185 kb |
File Type: | zip |
Animation clip 與 Animator 控制器練習 (3D)
發呆(Idle) ==> 走路 (左轉前進右轉) : 使用 1D Blend Tree
教學影片( 12 分鐘)
https://youtu.be/y65W5eShkpM
https://youtu.be/y65W5eShkpM
// 用到的腳本:
///blending.cs
using UnityEngine;
using System.Collections;
public class blending : MonoBehaviour {
private Animator anim;
private float h;
private float v;
// Use this for initialization
void Start () {
anim = GetComponent<Animator> ();
}
// Update is called once per frame
void Update () {
h = Input.GetAxis ("Horizontal");
v = Input.GetAxis ("Vertical");
anim.SetFloat ("Walk", v);
anim.SetFloat ("Turn", h);
}
}
/// 注意 Animator 那邊要弄兩個Float 參數(Parameter) :
Walk 和 Turn
官方網站教學
Animate Anything with Mecanim
//DoorActivator.cs
using UnityEngine;
using System.Collections;
public class DoorActivator : MonoBehaviour {
public Animator[] lights;
private Animator animator;
void Awake () {
animator = GetComponent <Animator>();
}
void OnTriggerEnter (Collider other) {
if (other.gameObject.tag == "Player") {
animator.SetBool ("Open", true);
foreach (var light in lights) {
light.SetTrigger ("Activate");
}
}
}
void OnTriggerExit (Collider other) {
if (other.gameObject.tag == "Player") {
animator.SetBool ("Open", false);
}
}
}
阿葉的Unity3D密技「Mecanim Animator Controller 由淺入深」 (90分鐘)
素材包以及程式碼參考(GoogleDrive) :
https://drive.google.com/drive/folders/0B0Jy9V02wfUcS2JwUjIyRVNyQTg?usp=sharing
但是他的英文不太好, 不要學他的發音 :-)
例如 false(假的) 他會念成 廢喔死
其實應該念 Four 匙
例如 false(假的) 他會念成 廢喔死
其實應該念 Four 匙
他講到那句關於"保險" ..
if( !Anim.IsInTransition(0) ) {
// 正確的意思是 如果動畫 不是 正在轉移狀態
}
if( !Anim.IsInTransition(0) ) {
// 正確的意思是 如果動畫 不是 正在轉移狀態
}
/// 宣告
Rigidbody2D myRigidbody2D;
[Header("左右移動的力量倍數 SpeedX")]
public float speedX = 33f;
[Header("跳的力氣 JumpForce")]
public float jumpForce = 5566f;
Rigidbody2D myRigidbody2D;
[Header("左右移動的力量倍數 SpeedX")]
public float speedX = 33f;
[Header("跳的力氣 JumpForce")]
public float jumpForce = 5566f;
///要讓玩家用鍵盤控制角色移動通常有三種方法
/// 第一種控制方法 : 直接取得左右箭頭按下的值 (-1 到 1 之間)
myRigidbody2D = new Vector2(
Input.GetAxis("Horizontal") * speedX,
myRigidbody2D.velocity.y);;;
///第二種方法是對左右按鍵分別給予剛體一個力氣 (force)
//查看是否按了右箭頭
if (Input.GetKey(KeyCode.RightArrow))
myRigidbody2D.AddForce(Vector2.right * speedX);
///// Vector2.right 就是 new Vector(1,0)
//看看是否按了左箭頭
if (Input.GetKey(KeyCode.LeftArrow))
myRigidbody2D.AddForce(Vector2.left * speedX);
if (Input.GetKey(KeyCode.RightArrow))
myRigidbody2D.AddForce(Vector2.right * speedX);
///// Vector2.right 就是 new Vector(1,0)
//看看是否按了左箭頭
if (Input.GetKey(KeyCode.LeftArrow))
myRigidbody2D.AddForce(Vector2.left * speedX);
///第三種方法是直接計算與改變遊戲物件的位置
(這方法因為與物理引擎無關, 遊戲物件可以沒有帶剛體)
(這方法因為與物理引擎無關, 遊戲物件可以沒有帶剛體)
///// 讓玩家控制角色跳躍 (Jump)
if (Input.GetButtonDown("Jump"))
myRigidbody2D.AddForce(new Vector2(0, jumpForce));
///請注意 jumpForce 要事先宣告(前面暫給 5566f)
myRigidbody2D.AddForce(new Vector2(0, jumpForce));
///請注意 jumpForce 要事先宣告(前面暫給 5566f)
==GameManager== (from 陳間時光)
/// 如何只保留一份遊戲管理物件(最開始的那份)
/// 如何只保留一份遊戲管理物件(最開始的那份)
/// GameManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour {
//singleton
//單例模式
static GameManager instance;
public int money;
void Awake () {
if (instance==null)
{
instance = this;
DontDestroyOnLoad(this);
name = "最初的遊戲管理物件";
money = 0;
}
else if (this!=instance)
{
string sceneName = SceneManager.GetActiveScene().name;
Debug.Log("刪除場景"+sceneName+"的"+name);
Destroy(gameObject);
}
}
void Update () {
}
}
==Door==
// 撞到門, 進入另一個場景 (載入場景)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Door : MonoBehaviour {
[Header("連接到某場景")]
public string goToTheScene;
void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("玩家"))
{
SceneManager.LoadScene(goToTheScene);
}
}
}
==Gold==
/// 碰到金幣, 賺 10 元
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gold : MonoBehaviour {
GameManager gameManager;
void Awake()
{
gameManager = FindObjectOfType<GameManager>();
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("玩家"))
{
gameManager.money += 10;
Debug.Log("金錢="+gameManager.money);
}
}
}
Left/Right test function
It is easy to get the angle between two vectors using Vector3.Angle,
but this only gives an absolute value for the angle.
How do you tell if one direction is to the left or to the right of the other?
but this only gives an absolute value for the angle.
How do you tell if one direction is to the left or to the right of the other?
/// C# version
//returns -1 when to the left, 1 to the right, and 0 for forward/backward
public float AngleDir(Vector3 fwd, Vector3 targetDir, Vector3 up)
{
Vector3 perp = Vector3.Cross(fwd, targetDir);
float dir = Vector3.Dot(perp, up);
if (dir > 0.0f) {
return 1.0f;
} else if (dir < 0.0f) {
return -1.0f;
} else {
return 0.0f;
}
}
//returns -1 when to the left, 1 to the right, and 0 for forward/backward
public float AngleDir(Vector3 fwd, Vector3 targetDir, Vector3 up)
{
Vector3 perp = Vector3.Cross(fwd, targetDir);
float dir = Vector3.Dot(perp, up);
if (dir > 0.0f) {
return 1.0f;
} else if (dir < 0.0f) {
return -1.0f;
} else {
return 0.0f;
}
}
//////////// another version
float AngleDir(Vector3 fwd, Vector3 targetDir, Vector3 up) {
Vector3 right = Vector3.Cross(up, fwd); // right vector
float dir = Vector3.Dot(right, targetDir);
if (dir > 0f) {
return 1f;
} else if (dir < 0f) {
return -1f;
} else {
return 0f;
}
}
///////////
///static version , javaScript
////////
//returns -1 when to the left, 1 to the right, and 0 for forward/backward
public static function AngleDir(fwd: Vector3, targetDir: Vector3, up: Vector3) : float {
var perp: Vector3 = Vector3.Cross(fwd, targetDir);
var dir: float = Vector3.Dot(perp, up);
if (dir > 0.0) {
return 1.0;
} else if (dir < 0.0) {
return -1.0;
} else {
return 0.0;
}
}
///
MoveTowards Example
There is no difference between 2D and 3D with respect to moving to the mouse position. An Orthographic camera does simplify the code a bit (2D or 3D).
要把遊戲物件移動到滑鼠點下的位置,
在 2D 和 3D 的做法並無差別;
要注意的是 2D 內的 z 軸位置也是有意義的 !
記得要把 target 的 z 軸位置改為與原先 transform 的 z 軸位 一樣,
否則你可能會發現物件走一段之後會憑空消失 !
要把遊戲物件移動到滑鼠點下的位置,
在 2D 和 3D 的做法並無差別;
要注意的是 2D 內的 z 軸位置也是有意義的 !
記得要把 target 的 z 軸位置改為與原先 transform 的 z 軸位 一樣,
否則你可能會發現物件走一段之後會憑空消失 !
Here is a bit of starter code. If you Google "Unity3d move towards mouse position," you will find other solutions.
///// 主要是須用到以下這句把滑鼠點到的螢幕位置轉為世界座標
Vector3 target = Camera.main.ScreenToWorldPoint (Input.mousePosition);
using UnityEngine;
using System.Collections;
public class GotoMouse : MonoBehaviour {
public float speed = 38.5f;
private Vector3 target;
void Start () {
target = transform.position;
}
void Update () {
checkKeyBoard( ); // 讓玩家也可用鍵盤左右箭頭按鍵
checkMouse ( ) ;
transform.position = Vector3.MoveTowards(
transform.position, target, speed * Time.deltaTime);
}
///
void checkKeyBoard( ) {
float gg = Input.GetAxisRaw("Horizontal"); // -1, 0, 1
if( gg == 0) return;
transform.position = new Vector3( transform.position .x + gg * speed * Time.deltaTime,
transform.position.y , transform.position .z );
setAnim(gg);
}
void setAnim(float gg) { // 預留要改變動畫的方向
// 1.利用改transform.localScale.x就可改變動畫的方向避免倒退魯
//2.必要時把 gg 設定到 Animator 的參數
} // setAnim(
void checkDir(float here, float there) {
float dir = 0f;
if(there > here) dir = 1f;
if(there < here) dir = -1f;
setAnim(dir);
}
void checkMouse ( ) {
if (Input.GetMouseButtonDown(0)) {
target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
target.z = transform.position.z;
checkDir(transform.position.x, target .position.x);
}
} // checkMouse (
}
如果還要兼顧動畫的方向呢(避免倒退魯!)
/// 假設 Animator 裡面有參數(Parameter) Direction
public class mousepos : MonoBehaviour {
private Animator anim;
public float speed = 13.5f;
private Vector3 target;
private Vector3 MousePosition;
private Vector3 PlayerPosition;
void Start () {
anim = GetComponent<Animator>();
target = transform.position;
}
///
void Update () {
checkMouse( );
checkKeyBoard( );
transform.position = Vector3.MoveTowards (
transform.position, target,
speed * Time.deltaTime);
} // Update(
void checkMouse( ) {
float dir = 0f;
float origX = 0f;
if (Input.GetMouseButtonDown (0)) {
target = Camera.main.ScreenToWorldPoint (Input.mousePosition);
origX = transform.position.x;
Debug.Log ("target 的 z 軸 = " + target.z + ", 會被改為 " + transform.position.z);
target.z = transform.position.z;
if (target.x <= origX) { // 在左邊
dir = transform.localScale.x;
if(dir > 0) dir = -dir; // 確保負數
setDirection(dir);
} else if (target.x >= origX) { // 在右邊
dir = transform.localScale.x;
if(dir < 0) dir = -dir; // 確保正數
setDirection(dir);
} // else if .. 左邊 .. 右邊
} // if 按下滑鼠
}
void setDirection(float dir) {
transform.localScale = new Vector3 (dir,
transform.localScale.y, transform.localScale.z);
if(dir >= 0) anim.SetInteger ("Direction", 1);
else anim.SetInteger ("Direction", -1);
}
void checkKeyBoard( ) {
}
} // class