Unity学习

来源:互联网 发布:iap 元数据丢失 编辑:程序博客网 时间:2024/06/05 11:22
Unity Introduction
What is Unity?
Unity is a cross-platform game engine developed by Unity Technologies and used to develop video games for PC, consoles, mobile devices and websites. First released on June 8, 2005
(from wiki))


Why should we study Unity?
Cross-platform
Free
Complete SDK documentation
Many free assets


Which programming language are we using?
C# (推荐入门书籍《C#入门经典》)
Javascript
Boo


Unity Tutorial Study
Website: Unity Tutorials
ROLL-A-BALL


Game Introduction
控制小球移动收集场景里的方块,UI会显示当前收集的方块数量,当所有方块通过碰撞收集后游戏UI提示You Win


Code
PlayerController.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;


public class PlayerController : MonoBehaviour {
public float m_Speed;


public Text m_CountText;


public Text m_WinText;


private Rigidbody m_RB;


private int m_Count;


void Start()
{
m_RB = GetComponent<Rigidbody> ();
m_Count = 0;
SetCountText();
m_WinText.text = "";
}


void FixedUpdate()
{
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");


Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
m_RB.AddForce (movement * m_Speed);
}


void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag ("Pickup")) 
{
other.gameObject.SetActive(false);
m_Count++;
SetCountText();
}
}


void SetCountText()
{
m_CountText.text = "Count: " + m_Count.ToString();
if (m_Count >= 12) 
{
m_WinText.text = "You Win!";
}
}
}


CameraController.cs
using UnityEngine;
using System.Collections;


public class CameraController : MonoBehaviour {
public GameObject m_Player;


private Vector3 m_Offset;


// Use this for initialization
void Start () {
m_Offset = transform.position - m_Player.transform.position;
}

// Update is called once per frame
void LateUpdate () {
transform.position = m_Player.transform.position + m_Offset;
}
}
Rotator.cs
1
using UnityEngine;
using System.Collections;


public class Rotator : MonoBehaviour {


// Use this for initialization
void Start () {

}

// Update is called once per frame
void Update () {
transform.Rotate (new Vector3 (15, 35, 45) * Time.deltaTime);
}
}
Captures:
Game Play
Roll_A_Ball_Game_Play
Roll_A_Ball_Game_Play


Win Game
Roll_A_Ball_Game_Win
Roll_A_Ball_Game_Win


SPACE SHOOTER
Game Introduction
Top Down Game
好比全民打飞机


Code
ShipController.cs
using UnityEngine;
using System.Collections;


[System.Serializable]
public class Boundary
{
public float m_MinX,m_MaxX,m_MinZ,m_MaxZ;
}


public class ShipController : MonoBehaviour {


public float m_Speed = 8;


public float m_Tilt = 4;

public float fireRate = 0.5F;


private float nextFire = 0.0F;


public Boundary m_Boundary;


public GameObject m_Shot;


public Transform m_ShotSpawn;


private AudioSource m_FireAudio;

private Rigidbody m_ShipRB;


private GameController m_GameController;


// Use this for initialization
void Start () {
m_ShipRB = GetComponent<Rigidbody> ();
m_FireAudio = GetComponent<AudioSource> ();
GameObject gamecontrollerobject = GameObject.FindGameObjectWithTag ("GameController");
if (gamecontrollerobject != null) {
m_GameController = gamecontrollerobject.GetComponent<GameController>();
}
if (m_GameController == null) {
Debug.Log("m_GameController == null in ShipController::Start()");
}
}


void Update(){
if (Input.GetKey(KeyCode.J) && Time.time > nextFire) {
nextFire = Time.time + fireRate;
GameObject clone = Instantiate (m_Shot, m_ShotSpawn.position, m_ShotSpawn.rotation) as GameObject;
m_FireAudio.Play();
}
}


void FixedUpdate(){
if (!m_GameController.IsGameEnd ()) {
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
m_ShipRB.velocity = movement * m_Speed;


m_ShipRB.position = new Vector3 (
Mathf.Clamp (m_ShipRB.position.x, m_Boundary.m_MinX, m_Boundary.m_MaxX),
0.0f,
Mathf.Clamp (m_ShipRB.position.z, m_Boundary.m_MinZ, m_Boundary.m_MaxZ)
);
m_ShipRB.rotation = Quaternion.Euler (0.0f, 0.0f, -m_ShipRB.velocity.x * m_Tilt);
} else {
m_ShipRB.rotation = Quaternion.Euler(0.0f,0.0f,0.0f);
m_ShipRB.velocity = new Vector3(0.0f,0.0f,0.0f);
}
}
}


GameController.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;


public class GameController : MonoBehaviour {


public GameObject m_Hazard;


public Vector3 m_SpawnValue = new Vector3(5.5f,0.0f,8.0f);


public int m_HazardCount = 4;


public float m_SpawnWait = 1.0f;


public float m_StartWait = 3.0f;


public float m_WaveWait = 4.0f;


public Text m_ScoreText;


public Text m_WinText;


public Button m_RestartButton;


public int m_WinningScore = 200;


private int m_Score = 0;


private bool m_IsGameEnd = false;


private bool m_RestartGame = false;


private AudioSource m_BackgroundAudio;


// Use this for initialization
void Start () {
StartCoroutine (SpawnAsteriod());
UpdateScore ();
m_WinText.text = "";
m_RestartButton.gameObject.SetActive (false);
m_RestartButton.onClick.AddListener (RestartGame);
m_BackgroundAudio = GetComponent<AudioSource> ();
}


void Update()
{
if (m_RestartGame) {
Debug.Log("Restart Game Now");
Application.LoadLevel(Application.loadedLevel);
}
}


public bool IsGameEnd()
{
return m_IsGameEnd;
}


private void RestartGame()
{
Debug.Log("Restart Button clicked");
m_RestartGame = true;
}


IEnumerator SpawnAsteriod(){
yield return new WaitForSeconds (m_StartWait);
while (true) {
for (int i = 0; i < m_HazardCount; i++) {
Vector3 spawnposition =  new Vector3 (Random.Range (-m_SpawnValue.x, m_SpawnValue.x), 0.0f, m_SpawnValue.z);
Quaternion spawnrotation = Quaternion.identity;
Instantiate(m_Hazard,spawnposition,spawnrotation);
yield return new WaitForSeconds (m_SpawnWait);
}
yield return new WaitForSeconds (m_WaveWait);
if(m_IsGameEnd)
{
break;
}
}
}


public void AddScore(int score)
{
m_Score += score;
UpdateScore ();
}


void UpdateScore()
{
m_ScoreText.text = "Score: " + m_Score;
if (m_Score >= m_WinningScore) {
m_WinText.text = "Congratulation! You Win";
m_IsGameEnd = true;
m_RestartButton.gameObject.SetActive (true);
m_BackgroundAudio.Stop();
}
}
}


DestroyByContact.cs
using UnityEngine;
using System.Collections;


public class DestroyByContact : MonoBehaviour {


public GameObject m_ExplosionObject;


public GameObject m_PlayerExplosionObject;


private GameController m_GameController;


public int m_ScoreValue = 10;


void Start()
{
GameObject gamecontrollerobject = GameObject.FindGameObjectWithTag ("GameController");
if (gamecontrollerobject != null) {
m_GameController = gamecontrollerobject.GetComponent<GameController>();
}
if (m_GameController == null) {
Debug.Log("m_GameController == null");
}
}


void OnTriggerEnter(Collider other) {
if (other.tag == "Boundary") {
return ;
}
Debug.Log ("other.tag = " + other.tag);


Instantiate (m_ExplosionObject, transform.position, transform.rotation);
if (other.tag == "Player") {
Instantiate (m_PlayerExplosionObject, other.transform.position, other.transform.rotation);
}
if (other.tag == "Bullet") {
Debug.Log("Asteriod is destroied by Bullet");
m_GameController.AddScore(m_ScoreValue);
}
Destroy(other.gameObject);
Destroy (gameObject);
}
}


DestroyByTime.cs
using UnityEngine;
using System.Collections;


public class DestroyByTime : MonoBehaviour {


public float m_LifeTime = 5.0f;


// Use this for initialization
void Start () {
Destroy (gameObject,m_LifeTime);
}
}
GameBoundary.cs
1
using UnityEngine;
using System.Collections;


public class GameBoundary : MonoBehaviour {


void OnTriggerExit(Collider other) {
Destroy(other.gameObject);
}
}
Mover.cs
1
using UnityEngine;
using System.Collections;


public class Mover : MonoBehaviour {


public float m_Speed = 8;


private Rigidbody m_RigidBody;

private GameController m_GameController;


// Use this for initialization
void Start () {
m_RigidBody = GetComponent<Rigidbody> ();
m_RigidBody.velocity = transform.forward * m_Speed;
GameObject gamecontrollerobject = GameObject.FindGameObjectWithTag ("GameController");
if (gamecontrollerobject != null) {
m_GameController = gamecontrollerobject.GetComponent<GameController>();
}
if (m_GameController == null) {
Debug.Log("m_GameController == null in ShipController::Start()");
}
}


void Update(){
if (m_GameController.IsGameEnd ()) 
{
m_RigidBody.rotation = Quaternion.Euler(0.0f,0.0f,0.0f);
m_RigidBody.velocity = new Vector3(0.0f,0.0f,0.0f);
}
}
}


RandomRotator.cs
using UnityEngine;
using System.Collections;


public class RandomRotator : MonoBehaviour {


public float m_Tumble = 5;


private Rigidbody m_Rigidbody;


// Use this for initialization
void Start () {
m_Rigidbody = GetComponent<Rigidbody> ();
m_Rigidbody.angularVelocity = Random.insideUnitSphere * m_Tumble;
}

// Update is called once per frame
void Update () {

}
}
Captures
Game Play
Space_Shooter_Game_Play
Space_Shooter_Game_Play


Win Game
Space_Shooter_Game_Win
Space_Shooter_Game_Win




Survival Shooter
Game Introduction
固定(2.5D -- isometric projection)第三人称视角游戏


Code
CameraFollow.cs
using UnityEngine;
using System.Collections;


public class CameraFollow : MonoBehaviour {

public Transform m_Target;

public float m_Smoothing = 5.0f;


Vector3 m_Offset;


// Use this for initialization
void Start () {
m_Offset = transform.position - m_Target.position;
}

// Update is called once per frame
void Update () {
Vector3 targetCamPos = m_Target.position + m_Offset;
transform.position = Vector3.Lerp (transform.position, targetCamPos, m_Smoothing * Time.deltaTime);
}
}


PlayerShooting.cs
using UnityEngine;


public class PlayerShooting : MonoBehaviour
{
    public int damagePerShot = 20;
    public float timeBetweenBullets = 0.15f;
    public float range = 100f;




    float timer;
    Ray shootRay;
    RaycastHit shootHit;
    int shootableMask;
    ParticleSystem gunParticles;
    LineRenderer gunLine;
    AudioSource gunAudio;
    Light gunLight;
    float effectsDisplayTime = 0.2f;




    void Awake ()
    {
        shootableMask = LayerMask.GetMask ("Shootable");
        gunParticles = GetComponent<ParticleSystem> ();
        gunLine = GetComponent <LineRenderer> ();
        gunAudio = GetComponent<AudioSource> ();
        gunLight = GetComponent<Light> ();
    }




    void Update ()
    {
        timer += Time.deltaTime;


if(Input.GetButton ("Fire1") && timer >= timeBetweenBullets && Time.timeScale != 0)
        {
            Shoot ();
        }


        if(timer >= timeBetweenBullets * effectsDisplayTime)
        {
            DisableEffects ();
        }
    }




    public void DisableEffects ()
    {
        gunLine.enabled = false;
        gunLight.enabled = false;
    }




    void Shoot ()
    {
        timer = 0f;


        gunAudio.Play ();


        gunLight.enabled = true;


        gunParticles.Stop ();
        gunParticles.Play ();


        gunLine.enabled = true;
        gunLine.SetPosition (0, transform.position);


        shootRay.origin = transform.position;
        shootRay.direction = transform.forward;


        if(Physics.Raycast (shootRay, out shootHit, range, shootableMask))
        {
            EnemyHealth enemyHealth = shootHit.collider.GetComponent <EnemyHealth> ();
Debug.Log("Shootting");
Debug.Log("shootHit.collider.name = " + shootHit.collider.name);


if(enemyHealth != null)
            {
Debug.Log("enermyHealth != null");
                enemyHealth.TakeDamage (damagePerShot, shootHit.point);
            }
            gunLine.SetPosition (1, shootHit.point);
        }
        else
        {
Debug.Log("Not shot");
            gunLine.SetPosition (1, shootRay.origin + shootRay.direction * range);
        }
    }
}


PlayerMovement.cs
using UnityEngine;


public class PlayerMovement : MonoBehaviour
{
public float m_Speed = 6.0f;


Vector3 m_Movement;


Animator m_Anim;


Rigidbody m_PlayerRigidbody;


int m_FloorMask;


float m_CamRayLength = 100.0f;


void Awake()
{
m_FloorMask = LayerMask.GetMask ("Floor");


m_Anim = GetComponent<Animator> ();


m_PlayerRigidbody = GetComponent<Rigidbody> ();
}


void FixedUpdate()
{
float h = Input.GetAxisRaw ("Horizontal");
float v = Input.GetAxisRaw ("Vertical");


Move (h, v);
Turning ();
Animating(h,v);
}


void Move(float h, float v)
{
m_Movement.Set (h, 0.0f, v);
m_Movement = m_Movement.normalized * m_Speed * Time.deltaTime;
m_PlayerRigidbody.MovePosition (transform.position + m_Movement);
}


void Turning()
{
Ray camRay = Camera.main.ScreenPointToRay (Input.mousePosition);


RaycastHit floorHit;


if(Physics.Raycast(camRay,out floorHit,m_CamRayLength, m_FloorMask))
   {
Vector3 playerToMouse = floorHit.point - transform.position;
playerToMouse.y = 0.0f;


Quaternion newRotation = Quaternion.LookRotation(playerToMouse);
m_PlayerRigidbody.MoveRotation(newRotation);
}
}


void Animating(float h, float v)
{
bool walking = (h != 0.0f || v != 0.0f);
m_Anim.SetBool ("IsWalking", walking);
}
}


PlayerHealth.cs
using UnityEngine;
using UnityEngine.UI;
using System.Collections;


public class PlayerHealth : MonoBehaviour
{
    public int startingHealth = 100;
    public int currentHealth;
    public Slider healthSlider;
    public Image damageImage;
    public AudioClip deathClip;
    public float flashSpeed = 5f;
    public Color flashColour = new Color(1f, 0f, 0f, 0.1f);




    Animator anim;
    AudioSource playerAudio;
    PlayerMovement playerMovement;
    //PlayerShooting playerShooting;
    bool isDead;
    bool damaged;




    void Awake ()
    {
        anim = GetComponent <Animator> ();
        playerAudio = GetComponent <AudioSource> ();
        playerMovement = GetComponent <PlayerMovement> ();
        //playerShooting = GetComponentInChildren <PlayerShooting> ();
        currentHealth = startingHealth;
    }




    void Update ()
    {
        if(damaged)
        {
            damageImage.color = flashColour;
        }
        else
        {
            damageImage.color = Color.Lerp (damageImage.color, Color.clear, flashSpeed * Time.deltaTime);
        }
        damaged = false;
    }




    public void TakeDamage (int amount)
    {
        damaged = true;


        currentHealth -= amount;


        healthSlider.value = currentHealth;


        playerAudio.Play ();


        if(currentHealth <= 0 && !isDead)
        {
            Death ();
        }
    }




    void Death ()
    {
        isDead = true;


        //playerShooting.DisableEffects ();


        anim.SetTrigger ("Die");


        playerAudio.clip = deathClip;
        playerAudio.Play ();


        playerMovement.enabled = false;
        //playerShooting.enabled = false;
    }




    public void RestartLevel ()
    {
        Application.LoadLevel (Application.loadedLevel);
    }
}


EnemyMovement.cs
using UnityEngine;
using System.Collections;


public class EnemyMovement : MonoBehaviour
{
    Transform player;
    PlayerHealth playerHealth;
    EnemyHealth enemyHealth;
    NavMeshAgent nav;




    void Awake ()
    {
        player = GameObject.FindGameObjectWithTag ("Player").transform;
        playerHealth = player.GetComponent <PlayerHealth> ();
        enemyHealth = GetComponent <EnemyHealth> ();
        nav = GetComponent <NavMeshAgent> ();
    }




    void Update ()
    {
        if(enemyHealth.currentHealth > 0 && playerHealth.currentHealth > 0)
        {
            nav.SetDestination (player.position);
        }
        else
        {
            nav.enabled = false;
        }
    }
}


EnemyHealth.cs
using UnityEngine;


public class EnemyHealth : MonoBehaviour
{
    public int startingHealth = 100;
    public int currentHealth;
    public float sinkSpeed = 2.5f;
    public int scoreValue = 10;
    public AudioClip deathClip;




    Animator anim;
    AudioSource enemyAudio;
    ParticleSystem hitParticles;
    CapsuleCollider capsuleCollider;
    bool isDead;
    bool isSinking;




    void Awake ()
    {
        anim = GetComponent <Animator> ();
        enemyAudio = GetComponent <AudioSource> ();
        hitParticles = GetComponentInChildren <ParticleSystem> ();
        capsuleCollider = GetComponent <CapsuleCollider> ();


        currentHealth = startingHealth;
isDead = false;
    }




    void Update ()
    {
        if(isSinking)
        {
            transform.Translate (-Vector3.up * sinkSpeed * Time.deltaTime);
        }
    }




    public void TakeDamage (int amount, Vector3 hitPoint)
    {
Debug.Log ("isDead = " + isDead);
        if(isDead)
            return;


        enemyAudio.Play ();


        currentHealth -= amount;
            
        hitParticles.transform.position = hitPoint;
        hitParticles.Play();


        if(currentHealth <= 0)
        {
            Death ();
        }
    }




    void Death ()
    {
        isDead = true;


        capsuleCollider.isTrigger = true;


        anim.SetTrigger ("Dead");


        enemyAudio.clip = deathClip;
        enemyAudio.Play ();
    }




    public void StartSinking ()
    {
        GetComponent <NavMeshAgent> ().enabled = false;
        GetComponent <Rigidbody> ().isKinematic = true;
        isSinking = true;
        ScoreManager.score += scoreValue;
        Destroy (gameObject, 2f);
    }
}


EnemyAttack.cs
using UnityEngine;
using System.Collections;


public class EnemyAttack : MonoBehaviour
{
    public float timeBetweenAttacks = 0.5f;
    public int attackDamage = 10;


public float validAttackDistance = 1.0f;


    Animator anim;
    GameObject player;
    PlayerHealth playerHealth;
    EnemyHealth enemyHealth;
    bool playerInRange;
    float timer;


    void Awake ()
    {
        player = GameObject.FindGameObjectWithTag ("Player");
        playerHealth = player.GetComponent <PlayerHealth> ();
        enemyHealth = GetComponent<EnemyHealth>();
        anim = GetComponent <Animator> ();
    }


/*
    void OnTriggerEnter (Collider other)
    {
        if(other.gameObject == player)
        {
            playerInRange = true;
        }
    }




    void OnTriggerExit (Collider other)
    {
        if(other.gameObject == player)
        {
            playerInRange = false;
        }
    }
    */


void OnCollisionEnter(Collision collision) {
if(collision.gameObject == player)
{
playerInRange = true;
}
}


void OnCollisionExit(Collision collision) {
if(collision.gameObject == player)
{
playerInRange = false;
}
}


    void Update ()
    {
/*
Vector3 attackDistance = player.transform.position - transform.position;
if (attackDistance.magnitude < validAttackDistance) {
playerInRange = true;
} else {
playerInRange = false;
}
*/
        timer += Time.deltaTime;


        if(timer >= timeBetweenAttacks && playerInRange && enemyHealth.currentHealth > 0)
        {
            Attack ();
        }


        if(playerHealth.currentHealth <= 0)
        {
            anim.SetTrigger ("PlayerDead");
        }
    }




    void Attack ()
    {
        timer = 0f;


        if(playerHealth.currentHealth > 0)
        {
            playerHealth.TakeDamage (attackDamage);
        }
    }
}




ScoreManager.cs
using UnityEngine;
using UnityEngine.UI;
using System.Collections;


public class ScoreManager : MonoBehaviour
{
    public static int score;




    Text text;




    void Awake ()
    {
        text = GetComponent <Text> ();
        score = 0;
    }




    void Update ()
    {
        text.text = "Score: " + score;
    }
}


EnemyManager.cs
using UnityEngine;


public class EnemyManager : MonoBehaviour
{
    public PlayerHealth playerHealth;
    public GameObject enemy;
    public float spawnTime = 3f;
    public Transform[] spawnPoints;




    void Start ()
    {
        InvokeRepeating ("Spawn", spawnTime, spawnTime);
    }




    void Spawn ()
    {
        if(playerHealth.currentHealth <= 0f)
        {
            return;
        }


        int spawnPointIndex = Random.Range (0, spawnPoints.Length);


        Instantiate (enemy, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
    }
}


GameOverManager.cs
using UnityEngine;


public class GameOverManager : MonoBehaviour
{
    public PlayerHealth playerHealth;




    Animator anim;




    void Awake()
    {
        anim = GetComponent<Animator>();
    }




    void Update()
    {
Debug.Log ("playerHealth.currentHealth = " + playerHealth.currentHealth);
        if (playerHealth.currentHealth <= 0)
        {
            anim.SetTrigger("GameOver");
        }
    }
}


Captures
Game Play
Survival_Shooter_Game_Play
Survival_Shooter_Game_Play


Win Game
Survival_Shooter_Game_Win
Survival_Shooter_Game_Win


编辑器界面
Hierachy
游戏组成元素(这个tutorial里,好比小球,方块,地面,摄像机,灯光,墙等)
主要用于对物件的归类管理
Create Empty可以用于层次管理归类


Project
游戏原件管理(这个tutorial里,好比材质,C#脚本)
主要用于对一次性资源的归类管理
可通过创建Folder进行资源整理归类


Scene
编辑场景
右上角可以切换视角
可以切换Local和Global模式进行移动物体


Game
运行时场景(可动态编辑查看物体属性)
Inspector
对象属性查看
通过物体名字左边的Active勾选框可以决定物体是否在编辑器可见可选
可以通过点击界面的?来打开相应面板的介绍页面


工具
MonoDevelop
C#,Js脚本编辑器(也可自己设定编辑器为VS Edit->Preference->External Tools->External Script Editor)


相关概念学习
Layout — 排版,可用于存储我们在Unity里面的面板排版设置,通过制定layout使用特定排版
Prefab — 原件,可在场景里重复利用,而且Prefab的改变可以通过点击Inspector界面的Apply影响到所有从该Prefab里创建出的对象
Tag — Scene里面所有物体的唯一标识,用于确保正确识别物体,通过对物体添加tag可以在程序里用于身份判别
Static collider — will not be affected by collision (not cause collide). Unity keep static collider mesh in cach
Dynamic collider — will be affected by collision
Is Trigger — when no collide caused(e.g. static collider), we can use trigger to enter collide event(只有没有物理碰撞的物体才会触发Trigger的)
Rigibody body — Moved by using physical force, use dynamic collider
Kinematic body — Moved by using the transform instead of physical force
Mesh Collider — Use Model mesh as collider mesh (一般只用于简单的三角形数量少的mesh)
AudioSource — 声音在Unity里也是组件的形式存在
C# Script — 每个物体可以绑定多个脚本用于不同逻辑,特别是用于原件一些特有的逻辑特性
2.5D -- 在3D的世界里通过平行投影(Orthographic Projection - isometric projection)实现
Raycast -- 射线碰撞检测(Physics.Raycast()在物体是is triiger on的时候不会触发)
LayerMask -- 可以用于选择和射线检测过滤
NavMeshAgent -- Unity的Navigation system可以提供最基本的路径AI寻址(只需要指定agent相关参数,在代码里设定跟踪目标) -- 添加后需要Bake Navigation
Animation Controller -- 动画管理,通过给物体添加Animator并设定动画状态机之间的切换规则来实现动画状态切换管理(通过给UI添加Animator我们也可以在Anmation面板设置简单动画)
LineRenderer -- 可以用于在3D世界里绘制线条,实现可视化一些射线检测物体碰撞等
Select icon -- 可以给没有实际物体或透明物体一个颜色标记(容易看到3D世界位置)
Canvas -- 画布是所有UI所应该在的区域(UI的层级关系会影响渲染顺序) -- 通过设定Render Mode实现不同的效果(Screen Space - Overlay不会受Camera的投影方式影响,永远在场景上. Screen Space - Camera会受Camera的投影方式影响,比如在透视投影里就会有近大远小的效果. World Space会把UI当做3D空间里的物体来对待,有深度概念会被遮挡 ))




快捷键学习
F — 在Scene界面选中对象后可以快速聚焦到该物体
Ctrl + ‘ — 打开脚本的类Reference page
Ctrl + D — Duplicated(复制)物体


项目编译发布
File -> Build Setting 设置平台
Drag Scene file to Scenes to build 选择要编译的场景
点击Build 编译游戏


C#脚本
public成员 — 编辑器可见可编辑
[System.Serializable] — 标志该类可以被序列化到Inspector


C#学习
Book down load link: c#入门经典第五版















































0 0
原创粉丝点击