<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Unity2d速通

      1 概述

      關于Unity正文前,先大致整理一些預備內容和框架。

      • Unity是一個平臺/引擎,有很多庫文件,開發者需要做兩件事:利用Unity自帶的圖形化界面(Inspector面板)掛載調整;利用自己寫的C#(Script腳本)調用庫文件實現邏輯。

      • 一個Unity工程有多個場景(Scene),每個場景下有多個對象(GameObject,也稱物件),一個對象就是一個容器(Container),容器中有很多組件(Component),一個組件有很多屬性(Attribute)。

      • 通常一個Unity2d項目的對象包括:基礎(Camera、EventSystem、Light等)、環境(Background、Midground、Foreground等)、游戲(Player、Enemy等)、用戶界面(Canvas、UI Elements等)。

      • Unity的xyz坐標系是左手系。對于在3D場景中z坐標更小(朝外)但圖層更低的對象,在2D中會被z坐標更大(朝里)的對象遮住。

      • 做好的復用對象模版保存在預制體(Prefab)中。整體Assets文件夾通常包括Art、Animation、Prefab、Scene、Script等。

      • 如果需要共享工程,只需要打包Assets、Packages、ProjectSettings三個文件夾。

      2 C#

      好了,讓我們學習代碼基礎。

      2.1 讓變量顯示在Inspector面板

      兩種方式:SerializeField(序列化字段)或Public(公有)。

          [SerializeField] private float walkSpeed = 1;
          public float jumpForce = 45f;
      

      區別在于SerializeField仍保持封裝不被外部腳本修改(推薦),Public的變量則是完全公開修改的。

      通常為了易讀性,這樣組織變量定義:

          [Header("Ground Check Settings:")]
          [SerializeField] private Transform groundCheckPoint; //point at which ground check happens
          [SerializeField] private float groundCheckY = 0.2f; //how far down from ground chekc point is Grounded() checked
          [SerializeField] private float groundCheckX = 0.5f; //how far horizontally from ground chekc point to the edge of the player is
          [SerializeField] private LayerMask whatIsGround; //sets the ground layer
          [Space(5)]
      

      可以在定義時賦值或不賦值。

      2.2 生命周期函數

      • Awake():初始化,最先調用

      • OnEnable():對象被啟用時調用

      • Start():在Awake()和OnEnable()之后調用

      • FixedUpdate():按固定間隔,多幀調用

      • Update():每幀調用

      • LateUpdate():在Update()之后,每幀調用

      • OnDisable():對象被禁用時調用

      • OnDestroy():對象被銷毀時調用

      單例模式(Singleton)的類在同一時刻只存在一個實例(比如玩家角色就是單例),并且提供全局訪問點,是典型的Awake()函數實現:

          private void Awake()
          {
              if (Instance != null && Instance != this)
              {
                  Destroy(gameObject);
              }
              else
              {
                  Instance = this;
              }
              DontDestroyOnLoad(gameObject);
          }
      

      Start()通常用于獲取組件和屬性,為了避免后面每一幀Update()頻繁調用,例如:

          void Start()
          {
              pState = GetComponent<PlayerStateList>();
      
              rb = GetComponent<Rigidbody2D>();
              sr = GetComponent<SpriteRenderer>();
      
              anim = GetComponent<Animator>();
      
              gravity = rb.gravityScale;
      
              Health = maxHealth;
              Mana = mana;
              manaStorage.fillAmount = Mana;
          }
      

      Update()處理每一幀動畫,以下是一個完整的2D角色單幀處理流程:

          void Update()
          {
              if (pState.cutscene) return;
      
              GetInputs();
              UpdateJumpVariables();
      
              if (pState.dashing) return;
              RestoreTimeScale();
              FlashWhileInvincible();
              Move();
              Heal();
              CastSpell();
              if (pState.healing) return;
              Flip();
              Jump();
              StartDash();
              Attack();
          }
      

      FixedUpdate()用于處理多幀動作:

          private void FixedUpdate()
          {
              if (pState.dashing || pState.healing || pState.cutscene) return;
              Recoil();
          }
      

      2.3 獲取Input輸入

      這些可以在Input Manager調整,代碼如:

          void GetInputs()
          {
              xAxis = Input.GetAxisRaw("Horizontal");
              yAxis = Input.GetAxisRaw("Vertical");
              attack = Input.GetButtonDown("Attack");
          }
      

      2.4 地面檢測

      這個功能通常需要完成兩個步驟:將地面設置為專用圖層,然后給對象添加地面檢查點。

      圖層設置可以在Inspector中完成(指派Ground圖層為whatIsGround),地面檢查點作為子對象附加到父對象(groundCheck寬度小于父對象的Box Collider)。

      代碼可以這樣實現:

          public bool Grounded()
          {
              if (Physics2D.Raycast(groundCheckPoint.position, Vector2.down, groundCheckY, whatIsGround) 
                  || Physics2D.Raycast(groundCheckPoint.position + new Vector3(groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround) 
                  || Physics2D.Raycast(groundCheckPoint.position + new Vector3(-groundCheckX, 0, 0), Vector2.down, groundCheckY, whatIsGround))
              {
                  return true;
              }
              else
              {
                  return false;
              }
          }
      

      這里Raycast(射線檢測)指的是從起點沿著指定的方向發射一條射線,檢測是否與任何物體發生碰撞。Vector2和Vector3分別代表二維向量與三維向量,Vector2.down是正下方,groundCheckX和groundCheckY是檢測范圍長度。

      2.5 左右翻轉

      這可以通過一個狀態bool變量實現。

          public bool lookingRight;
      

      然后編寫代碼:

          void Flip()
          {
              if (xAxis < 0)
              {
                  transform.localScale = new Vector2(-Mathf.Abs(transform.localScale.x), transform.localScale.y);
                  pState.lookingRight = false;
              }
              else if (xAxis > 0)
              {
                  transform.localScale = new Vector2(Mathf.Abs(transform.localScale.x), transform.localScale.y);
                  pState.lookingRight = true;
              }
          }
      

      Transform是少數不需要手動GetComponent()的組件,其三個屬性分別是position、rotation、localscale。

      另外移動的代碼如下:

          private void Move()
          {
              if (pState.healing) rb.velocity = new Vector2(0, 0);
              rb.velocity = new Vector2(walkSpeed * xAxis, rb.velocity.y);
              anim.SetBool("Walking", rb.velocity.x != 0 && Grounded());
          }
      

      2.6 幀間時間deltatime

      為了避免幀率對時間造成影響,采用deltatime(每幀的時間流逝量)如:

          void Attack()
          {
              timeSinceAttack += Time.deltaTime;
              if (attack && timeSinceAttack >= timeBetweenAttack)
              {
                  timeSinceAttack = 0;
                  anim.SetTrigger("Attacking");
      
                  if (yAxis == 0 || yAxis < 0 && Grounded())
                  {
                      Hit(SideAttackTransform, SideAttackArea, ref pState.recoilingX, recoilXSpeed);
                      Instantiate(slashEffect, SideAttackTransform);
                  }
                  else if (yAxis > 0)
                  {
                      Hit(UpAttackTransform, UpAttackArea, ref pState.recoilingY, recoilYSpeed);
                      SlashEffectAtAngle(slashEffect, 80, UpAttackTransform);
                  }
                  else if (yAxis < 0 && !Grounded())
                  {
                      Hit(DownAttackTransform, DownAttackArea, ref pState.recoilingY, recoilYSpeed);
                      SlashEffectAtAngle(slashEffect, -90, DownAttackTransform);
                  }
              }
      

      這里也用到了自定義的計時器,用于控制時間間隔。如果涉及Time.timeScale,那么Time.unscaledDeltaTime則是不受縮放影響的真實時間,Time.deltaTime會受到更改。

      2.7 可視化調試OnDrawGizmos

      這種方法只在編輯模式和游戲模式下的場景視圖中起作用,不會在實際游戲運行時的屏幕上顯示。

          private void OnDrawGizmos()
          {
              Gizmos.color = Color.red;
              Gizmos.DrawWireCube(SideAttackTransform.position, SideAttackArea);
              Gizmos.DrawWireCube(UpAttackTransform.position, UpAttackArea);
              Gizmos.DrawWireCube(DownAttackTransform.position, DownAttackArea);
          }
      

      2.8 協程Coroutine

      協程用于處理需要一定時間完成的動作。以沖刺為例:

          IEnumerator Dash()
          {
              canDash = false;
              pState.dashing = true;
              anim.SetTrigger("Dashing");
              rb.gravityScale = 0;
              int _dir = pState.lookingRight ? 1 : -1;
              rb.velocity = new Vector2(_dir * dashSpeed, 0);
              if (Grounded()) Instantiate(dashEffect, transform);
              yield return new WaitForSeconds(dashTime);
              rb.gravityScale = gravity;
              pState.dashing = false;
              yield return new WaitForSeconds(dashCooldown);
              canDash = true;
          }
      

      3 面板

      3.1 圖像

      PPU(Pixels Per Unit)越大,導入圖片越小,畫面越清晰。

      Max Size是導入的圖片在縮放下不超過的最大尺寸,如果過小會使得畫面模糊。

      Filter Mode是過濾模式,通常多線性的紋理效果優于點線性。

      Wrap Mode是環繞模式,Repeat會在超出范圍時重復顯示,Clamp是鉗制。

      3.2 剛體

      Rigidbody處理物體的物理運動,包括重力、速度、力。

      注意如果子對象不是剛體,那么父對象的Collider是自己和子對象的Collider之和。此時子對象可以觸發父對象的OnTriggerEnter2D()。

      3.3 SortingLayer

      Unity有兩種自帶的圖層:Layer和Sorting Layer。前者如檢測碰撞用于圖層邏輯(邏輯分層),后者用于顯示渲染覆蓋(排序分層)。

      Sorting Layer在制作環境、背景時非常有用,可以制作景深、霧氣、特殊的前后遮擋效果等等。

      如果UI物件和場景物體相互遮蓋,可以在Layer中隱藏。

      3.4 URP Lighting

      2D Light在新版Unity中被放進URP(Universal Render Pipeline)Package中。

      為了添加Lighting,需要把所有被Light的對象材質換成URP材質。

      選擇需要的Sorting Layer添加2D Light,適當調整顏色和強度以匹配環境。

      4 動畫

      4.1 K幀

      K幀即關鍵幀動畫,通過在關鍵幀之間插值實現平滑過渡。

      Unity的K幀動畫在Animation窗口,樸素的方法是把預制的關鍵幀Sprite添加進去保存,會自動在Animator窗口生成狀態機,然后可以在代碼中調用如:

              anim.SetBool("Walking", rb.velocity.x != 0 && Grounded());
      

      這樣可以控制Animator的標記變量實現條件狀態轉移。

      4.2 骨骼動畫

      樸素的K幀消耗大量時間,這時可以用Unity的skinning editor處理分層的單張圖片(推薦psb/psd,也可以是png;Unity可以自動切割圖片,注意背景透明)。

      通常先綁定(Rigging)骨骼(如要細致動畫可在頭發或衣服上添加分叉的骨骼),并在Visualization分配骨骼排序。然后使用Auto Geometry生成權重,應用后在需要動畫的對象添加Sprite Skin組件創建骨骼。

      如果需要為同一個物件準備多個Sprite,那么都對其作綁定,后續動畫采用Sprite Resolver或Sprite Swap等組件設置同一個物件不同Sprite的可見性。

      武器裝備之類應當和角色骨骼層級相同,不應低于角色。

      4.3 IK反向動力學

      IK Manager可以實現子骨骼連續帶動父骨骼轉動的效果。

      這通常是把手、腳等邊緣骨骼掛載到IK Manager的List中,然后創建Target,并對翻轉、約束作調整。

      4.4 粒子系統ParticleSystem

      粒子系統可以制作動畫特效。

      首先需要粒子的Material,然后在層次面板創建粒子系統,在Inspector中配置。

      posted @ 2024-08-11 01:03  rainrzk  閱讀(61)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 天堂一区二区三区av| 亚洲综合网一区中文字幕| 石原莉奈日韩一区二区三区| 亚洲无码精品视频| 亚洲国产精品成人av网| 成人3d动漫一区二区三区| 性欧美暴力猛交69hd| 好紧好滑好湿好爽免费视频| 中文字幕va一区二区三区| 97久久超碰精品视觉盛宴| 无码福利写真片视频在线播放 | 亚洲欧美在线观看品| 亚洲高清国产自产拍av| 无码精品人妻一区二区三区中| 国产丝袜视频一区二区三区| 亚洲av第三区国产精品| 久久天天躁狠狠躁夜夜躁2020| 国产精品爽爽v在线观看无码| 天干天干夜天干天天爽| 久久月本道色综合久久| 亚洲人成电影网站色mp4| 亚洲国产精品综合久久网各 | 国产区一区二区现看视频| 国产精品久久久久9999| 久久精品人妻无码一区二区三区| 国内少妇偷人精品免费| 亚洲国产欧美不卡在线观看| 国产玖玖视频| 国产91特黄特色A级毛片| 国产一区二区三区内射高清| 亚洲日本欧洲二区精品| 久久精品一区二区三区中文字幕| 女人与牲口性恔配视频免费| 精品亚洲AⅤ无码午夜在线| 欧美日产国产精品日产| 免费十八禁一区二区三区| 中国xxx农村性视频| 欧美一区二区三区欧美日韩亚洲| 国产麻豆精品av在线观看| 四虎库影成人在线播放| 中文字幕国产日韩精品|