Unity第N+2堂

實例介紹

簡介

場景

匯入資源

  • 去unity asset store 找「Pixel Adventure 1」
  • 將他匯入專案中

畫場景

建立一個scenes叫「Lv1」

進到Lv1的場景

建立一個tilemap叫「background」

打開Tile Palette

Create New Palette 將Terrain裡的Terrain Slized拖進去(記得將Pixel Per Unit改為16

將background裡的全拖進去當背景(將Pixel Per Unit改為64

*作為路徑跟背景的tilemap記得分開

設定

將作為路徑的tilemap加上Tilemap Collider 2D(勾選used by composite)

Rigidbody 2D(改static)

Composite Collider 2D(勾選 used by effector)

Platfrom Effector 2D(取消勾選used one way)

 

player

建立角色

建立一個square叫player

將pink man 的Idle的第一個拖進sprite

加上Rigidbody 2D跟 Box Collider 2D

加入一個腳本讓他能動跟跳

private SpriteRenderer sprite;
private Animator anim;
private Rigidbody2D rb;
private BoxCollider2D coll;
private float dirX=0f;
[SerializeField] private float moveSpeed = 7f;
[SerializeField] private float jumpForce = 7f;
void Start()
{
    rb=GetComponent<Rigidbody2D>();
    coll = GetComponent<BoxCollider2D>();
    sprite = GetComponent<SpriteRenderer>();
    anim = GetComponent<Animator>();

    
}
void Update()
  {
      dirX=Input.GetAxisRaw("Horizontal");
      rb.velocity = new Vector2(dirX*moveSpeed,rb.velocity.y);
      if (Input.GetButtonDown("Jump"))
      {
          rb.velocity= new Vector2(rb.velocity.x,jumpForce);
      }

  }

動畫

private Animator anim;
private enum MovementState { idle,running,jumping,falling}
 private void UpdateAnimationState()
  {
      MovementState state;
      if(dirX > 0f)
      {
          state = MovementState.running;
          sprite.flipX = false;
      }
      else if(dirX < 0f)
      {
          state = MovementState.running;
          sprite.flipX = true;
      }
      else
      {
          state = MovementState.idle;
      }

      if(rb.velocity.y > .1f)
      {
          state = MovementState.jumping;
      }
      else if(rb.velocity.y < -.1f)
      {
          state = MovementState.falling;
      }

      anim.SetInteger("state", (int)state);
  }

Create -> Animation

拖到角色身上,會出現一個方形的東西

點開動畫

點一下角色後將全部拖進去

(Samples可以改速度

記得勾選loop time

點開那個方形的東西

會出現很多方塊跟線

將所有方塊用make transition連起來

添加一個int

按數組數字更改線的數字

(全部線取消勾選Has exit Time

Transition Duratio改成0

攝影機

添加一個腳本在main Camera上

記得把player拖進去腳本

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

public class camera : MonoBehaviour
{
    [SerializeField] private Transform player;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        transform.position = new Vector3(player.position.x, player.position.y, transform.position.z);
    }
}

下一關

旗子

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

public class Finish : MonoBehaviour
{
    private bool levelCompleted = false;
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.name == "player" && !levelCompleted)
        {
            levelCompleted = true;
            Invoke("CompleteLevel", 2f);
        }
    }

    private void CompleteLevel()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex +1);
    }
}

建立一個square

將checkpoint拖進去

建一個旗子的動畫

加上Box Collider 2D(勾選Is trigger

加入腳本

建新scene

去build setting->add open scene

收集

繼承

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

public class allcontrol : MonoBehaviour
{
    // Start is called before the first frame update

    public class GameManger 
    {
        private static GameManger _instance;

        public static GameManger Instance
        {
            get
            {
                if(_instance == null)
                    _instance = new GameManger();
                return _instance;
            }
        }
        public int score = 0;
    }
}

建立一個square

將cherry拖進去

添加一個tag叫cherry

建一個櫻桃的動畫

加上Box Collider 2D(勾選Is trigger

建一個腳本叫allcontrol

將左邊的東西貼進去

收集

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using static allcontrol;

public class collect : MonoBehaviour
{

    int cherries = GameManger.Instance.score;
    [SerializeField] private TMP_Text cherriesText;
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.CompareTag("cherry"))
        {
            Destroy(collision.gameObject);
            cherries++;
            cherriesText.text = "cherries:" + cherries;

            GameManger.Instance.score = cherries;
        }
    }
}

建一個UI->text

建一個腳本將左邊內容貼進去

將腳本拖到player上

將text拖到腳本裡

死亡

陷阱

建一個square將spikes拖進去

添加一個tag叫trap

移動陷阱

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

public class Rotate : MonoBehaviour
{
    [SerializeField] private float speed = 2f;

    private void Update()
    {
        transform.Rotate(0,0,360*speed*Time.deltaTime);
    }
}

建一個square將saw拖進去,添加trap的tag

create empty *2,將他們改成點

添加兩點來回的腳本(下一頁)

將點拖進去

添加轉動腳本(右邊)

添加box collider 2D

在兩點來回

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

public class waypointfollower : MonoBehaviour
{
    [SerializeField] private GameObject[] waypoints;
    private int currentWaypointIndex = 0;
    [SerializeField] private float speed = 2f;
    // Start is called before the first frame update
    

    // Update is called once per frame
    private void Update()
    {
        if (Vector2.Distance(waypoints[currentWaypointIndex].transform.position , transform.position) < .1f)
        {
            currentWaypointIndex++;
            if(currentWaypointIndex >= waypoints.Length)
            {
                currentWaypointIndex = 0;
            }
        }
        transform.position = Vector2.MoveTowards(transform.position, waypoints[currentWaypointIndex].transform.position, Time.deltaTime * speed);
    }
}

小補充--移動平台

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

public class stickyplatform : MonoBehaviour
{
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.name == "player")
        {
            collision.gameObject.transform.SetParent(transform);
        }
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        if( collision.gameObject.name == "player")
        {
            collision.gameObject.transform.SetParent(null);
        }
    }
    
}

前面都跟移動陷阱一樣

多了添加右邊的腳本跟再加一個

box collider 2D(勾選is trigger)

把範圍拉小

死亡

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class playerlife : MonoBehaviour
{
    private Rigidbody2D rb;
    private Animator anim;
    private void Start()
    {
        rb=GetComponent<Rigidbody2D>();
        anim=GetComponent<Animator>();
    }
    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("trap"))
        {
            Die();
        }
    }
    private void Die()
    {
        rb.bodyType = RigidbodyType2D.Static;
        anim.SetTrigger("death");
    }
    private void RestartLevel()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    }
}

新增消失動畫

將desappering的做成動畫

用錄製最後面取消sprite的勾勾

往後拉一段添加event選restart Level

在關係裡新增一個trigger叫death

any state連death線上選death

bgm

例子

[SerializeField] private AudioSource jumpSoundEffect;
if (Input.GetButtonDown("Jump"))
{
    jumpSoundEffect.Play();
}

匯入一堆音樂素材

將下面的腳本加到原本playermove裡面

在player上加Audio Source

將音檔拖進AudioClip(取消勾選play on awake

Audio Source拖到腳本裡

背景樂:

create empty

除了不用腳本其他一樣

(要勾選play on awake跟loop

開始畫面&結尾畫面

開始

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

public class startmenu : MonoBehaviour
{
    // Start is called before the first frame update

    public void StartGame()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
    }
    
}

新增一個scene

進去之後新增一個panel作為開始畫面

新增想要的UI

新增一個button

將以下腳本新增到button上

在on click選StartGame()

結束

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

public class endmenu : MonoBehaviour
{
    // Start is called before the first frame update

    public void ReloadGame()
    {
        SceneManager.LoadScene(0);
    }
    
}

跟開始一樣

*記得要加場景到build setting

Unity第N+2堂

By jellyfish

Unity第N+2堂

  • 102