Sa artikulong ito, patuloy kaming bumubuo ng controller ng character para sa isang 2D platformer sa Unity, na masusing sinusuri ang bawat hakbang ng pag-configure at pag-optimize ng mga kontrol.
Sa nakaraang artikulo, " Paano Gumawa ng 2D Character Controller sa Unity: Part 1 ", tinalakay namin nang detalyado kung paano lumikha ng pundasyon ng character, kasama ang pisikal na pag-uugali at pangunahing paggalaw nito. Ngayon, oras na upang lumipat sa mas advanced na mga aspeto, tulad ng paghawak ng input at dynamic na pagsubaybay sa camera.
Sa artikulong ito, susuriin natin ang pagse-set up ng bagong sistema ng pag-input ng Unity, paggawa ng mga aktibong pagkilos upang kontrolin ang karakter, pagpapagana ng paglukso, at pagtiyak ng mga wastong tugon sa mga utos ng manlalaro.
Kung gusto mong ipatupad ang lahat ng mga pagbabagong inilarawan sa artikulong ito sa iyong sarili, maaari mong i-download ang sangay ng repositoryo na " Katawan ng Karakter ", na naglalaman ng pundasyon para sa artikulong ito. Bilang kahalili, maaari mong i-download ang sangay ng " Character Controller " na may huling resulta.
Bago tayo magsimulang magsulat ng code para makontrol ang ating karakter, kailangan nating i-configure ang input system sa proyekto. Para sa aming platformer, pinili namin ang bagong Input System ng Unity, na ipinakilala ilang taon na ang nakalipas, na nananatiling may-katuturan dahil sa mga pakinabang nito sa tradisyonal na sistema.
Nag-aalok ang Input System ng mas modular at flexible na diskarte sa paghawak ng input, na nagbibigay-daan sa mga developer na madaling mag-set up ng mga kontrol para sa iba't ibang device at suportahan ang mas kumplikadong mga senaryo ng pag-input nang walang karagdagang overhead ng pagpapatupad.
Una, i-install ang package ng Input System. Buksan ang Package Manager mula sa pangunahing menu sa pamamagitan ng pagpili sa Window → Package Manager. Sa seksyon ng Unity Registry, hanapin ang package na "Input System" at i-click ang "I-install".
Susunod, pumunta sa mga setting ng proyekto sa pamamagitan ng Edit → Project Settings menu. Piliin ang tab na Player, hanapin ang seksyong Active Input Handling, at itakda ito sa "Input System Package (Bago).
Pagkatapos makumpleto ang mga hakbang na ito, ipo-prompt ka ng Unity na mag-restart. Kapag na-restart, magiging handa na ang lahat para i-configure ang mga kontrol para sa aming kapitan.
Sa folder ng Mga Setting , lumikha ng Mga Pagkilos sa Input sa pamamagitan ng pangunahing menu: Mga Asset → Gumawa → Mga Pagkilos sa Input . Pangalanan ang file na "Mga Kontrol."
Ang Unity's Input System ay isang malakas at flexible na tool sa pamamahala ng input na nagbibigay-daan sa mga developer na mag-configure ng mga kontrol para sa mga character at elemento ng laro. Sinusuportahan nito ang iba't ibang mga input device. Ang Input Actions na ginawa mo ay nagbibigay ng sentralisadong pamamahala ng input, pinapasimple ang pag-setup at ginagawang mas intuitive ang interface.
I-double click ang Controls file upang buksan ito para sa pag-edit, at magdagdag ng Action Map para sa control ng character na pinangalanang "Character."
Ang Action Map sa Unity ay isang koleksyon ng mga aksyon na maaaring iugnay sa iba't ibang controllers at key para magsagawa ng mga partikular na gawain sa laro. Ito ay isang mahusay na paraan upang ayusin ang mga kontrol, na nagbibigay-daan sa mga developer na maglaan at mag-adjust ng mga input nang walang muling pagsusulat ng code. Para sa higit pang mga detalye, sumangguni sa opisyal na dokumentasyon ng Input System .
Ang unang aksyon ay tatawaging "Ilipat." Ang pagkilos na ito ay tutukuyin ang direksyon ng paggalaw ng karakter. Itakda ang Uri ng Aksyon sa "Value" at ang Uri ng Kontrol sa "Vector2" upang paganahin ang paggalaw sa apat na direksyon.
Magtalaga ng mga binding sa pagkilos na ito sa pamamagitan ng pagpili sa Add Up/Down/Right/Left Composite at pagtatalaga ng pamilyar na WASD key sa kani-kanilang direksyon.
Huwag kalimutang i-save ang iyong mga setting sa pamamagitan ng pag-click sa Save Asset . Tinitiyak ng setup na ito na maaari mong italaga muli ang mga binding para sa pagkilos na "Ilipat," halimbawa, sa mga arrow key o kahit isang gamepad joystick.
Susunod, magdagdag ng bagong aksyon — "Jump." Panatilihin ang Uri ng Aksyon bilang "Button", ngunit magdagdag ng bagong Pakikipag-ugnayan — "Pindutin", at itakda ang Trigger Behavior sa "Press And Release", dahil kailangan nating makuha ang parehong pindutan na pindutin at bitawan.
Kinukumpleto nito ang scheme ng kontrol ng character. Ang susunod na hakbang ay ang pagsulat ng isang bahagi upang mahawakan ang mga pagkilos na ito.
Oras na para i-link ang Input Actions na ginawa namin para sa kontrol ng character sa CharacterBody
component, na nagbibigay-daan sa character na aktibong lumipat sa buong eksena ayon sa aming mga control command.
Para magawa ito, gagawa kami ng script na responsable para sa kontrol ng paggalaw at pangalanan itong CharacterController
para sa kalinawan. Sa script na ito, tutukuyin muna namin ang ilang mga pangunahing field. Magdaragdag kami ng reference sa CharacterBody
component, _characterBody
, na direktang kokontrolin ng script.
Magtatakda din kami ng mga parameter para sa bilis ng paggalaw ng character ( _speed
) at taas ng jump ( _jumpHeight
). Bilang karagdagan, tutukuyin namin ang layunin ng field na _stopJumpFactor
.
Maaaring napansin mo na sa maraming 2D platformer, ang taas ng pagtalon ay maaaring kontrolin. Kung mas matagal ang jump button ay hawak, mas mataas ang character na tumalon. Sa esensya, ang isang paunang pataas na bilis ay inilapat sa simula ng pagtalon, at ang bilis na ito ay nababawasan kapag ang pindutan ay binitawan. Tinutukoy ng _stopJumpFactor
kung gaano kalaki ang pagbaba ng pataas na bilis kapag binitawan ang jump button.
Narito ang isang halimbawa ng code na isusulat namin:
// CharacterController.cs public class CharacterController : MonoBehaviour { [SerializeField] private CharacterBody _characterBody; [Min(0)] [SerializeField] private float _speed = 5; [Min(0)] [SerializeField] private float _jumpHeight = 2.5f; [Min(1)] [SerializeField] private float _stopJumpFactor = 2.5f; }
Susunod, ipapatupad namin ang kakayahang ilipat ang character pakaliwa at pakanan. Kapag pinipigilan ang pindutan ng paggalaw, dapat mapanatili ng karakter ang tinukoy na bilis ng paggalaw anuman ang mga hadlang. Para makamit ito, magdadagdag kami ng variable sa script para iimbak ang kasalukuyang bilis ng paggalaw sa ibabaw (o pahalang lang kapag nasa eruplano ang karakter):
// CharacterController.cs private float _locomotionVelocity;
Sa bahagi ng CharacterBody
, ipapakilala namin ang isang paraan upang itakda ang bilis na ito:
// CharacterBody.cs public void SetLocomotionVelocity(float locomotionVelocity) { Velocity = new Vector2(locomotionVelocity, _velocity.y); }
Dahil ang aming laro ay hindi nagtatampok ng mga sloped surface, ang pamamaraang ito ay medyo simple. Sa mas kumplikadong mga sitwasyon, kailangan nating isaalang-alang ang estado ng katawan at ang slope sa ibabaw. Sa ngayon, pinapanatili lang namin ang vertical na bahagi ng bilis habang binabago lamang ang horizontal x
coordinate.
Susunod, itatakda namin ang halagang ito sa paraan Update
sa bawat frame:
// CharacterController.cs private void Update() { _characterBody.SetLocomotionVelocity(_locomotionVelocity); }
Tutukuyin namin ang isang paraan upang mahawakan ang mga signal mula sa Move
Input Action:
// CharacterController.cs public void OnMove(InputAction.CallbackContext context) { var value = context.ReadValue<Vector2>(); _locomotionVelocity = value.x * _speed; }
Dahil ang Move
action ay tinukoy bilang Vector2
, ang konteksto ay magbibigay ng vector value depende sa kung aling mga key ang pinindot o binibitiwan. Halimbawa, ang pagpindot sa D
key ay magreresulta sa paraan OnMove
na matanggap ang vector (1, 0). Ang pagpindot D
at W
nang sabay ay magreresulta sa (1, 1). Ang pag-release sa lahat ng key ay magti-trigger OnMove
na may value (0, 0).
Para sa A
key, ang vector ay magiging (-1, 0). Sa pamamaraang OnMove
, kinukuha namin ang pahalang na bahagi ng natanggap na vector at i-multiply ito sa tinukoy na bilis ng paggalaw, _speed
.
Una, kailangan nating turuan ang CharacterBody
component na pangasiwaan ang paglukso. Upang gawin ito, magdaragdag kami ng paraan na responsable para sa pagtalon:
// CharacterBody.cs public void Jump(float jumpSpeed) { Velocity = new Vector2(_velocity.x, jumpSpeed); State = CharacterState.Airborne; }
Sa aming kaso, ang paraang ito ay diretso: itinatakda nito ang vertical velocity at agad na binabago ang estado ng character sa Airborne
.
Susunod, kailangan nating matukoy ang bilis kung saan dapat tumalon ang karakter. Natukoy na namin ang taas ng pagtalon at alam na patuloy na kumikilos ang gravity sa katawan. Batay dito, ang paunang bilis ng pagtalon ay maaaring kalkulahin gamit ang formula:
Kung saan ang h ay ang taas ng pagtalon, at ang g ay ang gravitational acceleration. Isasaalang-alang din namin ang gravity multiplier na nasa CharacterBody
component. Magdaragdag kami ng bagong field para tukuyin ang paunang bilis ng pagtalon at kalkulahin ito bilang sumusunod:
// CharacterController.cs private float _jumpSpeed; private void Awake() { _jumpSpeed = Mathf.Sqrt(2 * Physics2D.gravity.magnitude * _characterBody.GravityFactor * _jumpHeight); }
Kakailanganin namin ng isa pang field para masubaybayan kung kasalukuyang tumatalon ang karakter, para malimitahan namin ang bilis ng pagtalon sa naaangkop na oras.
Bukod pa rito, kung hawak ng manlalaro ang jump button hanggang sa landing, dapat nating i-reset ang flag na ito sa ating sarili. Gagawin ito sa paraan Update
:
// CharacterController.cs private bool _isJumping; private void Update() { if (_characterBody.State == CharacterState.Grounded) { _isJumping = false; } //... }
Ngayon, isulat natin ang paraan upang pangasiwaan ang pagkilos Jump
:
// CharacterController.cs public void OnJump(InputAction.CallbackContext context) { if (context.started) { Jump(); } else if (context.canceled) { StopJumping(); } }
Dahil ang Jump
action ay isang button, matutukoy natin mula sa konteksto kung ang pagpindot sa button ay nagsimula ( context.started
) o natapos na ( context.canceled
). Batay dito, maaari naming simulan o ihinto ang pagtalon.
Narito ang paraan upang maisagawa ang pagtalon:
// CharacterController.cs private void Jump() { if (_characterBody.State == CharacterState.Grounded) { _isJumping = true; _characterBody.Jump(_jumpSpeed); } }
Bago tumalon, tinitingnan namin kung ang karakter ay nasa lupa. Kung gayon, itinakda namin ang bandilang _isJumping
at gagawing tumalon ang katawan gamit ang _jumpSpeed
.
Ngayon, ipatupad natin ang pag-uugaling huminto sa pagtalon:
// CharacterController.cs private void StopJumping() { var velocity = _characterBody.Velocity; if (_isJumping && velocity.y > 0) { _isJumping = false; _characterBody.Velocity = new Vector2( velocity.x, velocity.y / _stopJumpFactor); } }
Ihihinto lang namin ang pagtalon kung aktibo ang flag _isJumping
. Ang isa pang mahalagang kondisyon ay ang karakter ay dapat na gumagalaw paitaas. Pinipigilan nito ang paglilimita sa bilis ng pagkahulog kung ang pindutan ng pagtalon ay pinakawalan habang lumilipat pababa. Kung matugunan ang lahat ng kundisyon, ni-reset namin ang flag _isJumping
at binabawasan ang vertical velocity ng isang factor na _stopJumpFactor
.
Ngayon na handa na ang lahat ng mga bahagi, idagdag ang mga bahagi PlayerInput
at CharacterController
sa object ng Captain sa eksena. Siguraduhing piliin ang bahagi ng CharacterController
na aming ginawa, hindi ang karaniwang bahagi ng Unity na idinisenyo para sa pagkontrol sa mga 3D na character.
Para sa CharacterController
, italaga ang umiiral na CharacterBody
component mula sa character. Para sa PlayerInput
, itakda ang naunang ginawang Mga Kontrol sa field na Actions
.
Susunod, i-configure ang bahagi ng PlayerInput upang tawagan ang mga naaangkop na pamamaraan mula sa CharacterController. Palawakin ang mga seksyon ng Mga Kaganapan at Character sa editor, at i-link ang mga kaukulang pamamaraan sa mga pagkilos na Move and Jump.
Ngayon, handa na ang lahat para patakbuhin ang laro at subukan kung paano gumagana nang magkasama ang lahat ng naka-configure na bahagi.
Ngayon, kailangan nating gawin ang camera na sundin ang karakter saan man sila pumunta. Nagbibigay ang Unity ng mahusay na tool para sa pamamahala ng camera — Cinemachine .
Ang Cinemachine ay isang rebolusyonaryong solusyon para sa kontrol ng camera sa Unity na nag-aalok sa mga developer ng malawak na hanay ng mga kakayahan para sa paglikha ng mga dynamic, well-tuned na mga system ng camera na umaangkop sa mga pangangailangan ng gameplay. Pinapadali ng tool na ito na ipatupad ang mga kumplikadong diskarte sa camera, tulad ng pagsunod sa karakter, awtomatikong pagsasaayos ng focus, at marami pang iba, pagdaragdag ng sigla at kasaganaan sa bawat eksena.
Una, hanapin ang object ng Pangunahing Camera sa eksena, at idagdag ang bahagi ng CinemachineBrain
dito.
Susunod, lumikha ng bagong bagay sa eksenang pinangalanang CaptainCamera . Ito ang magiging camera na sumusunod sa kapitan, tulad ng isang propesyonal na cameraman. Idagdag ang bahagi ng CinemachineVirtualCamera
dito. Itakda ang Follow field sa kapitan, piliin ang Framing Transposer para sa Body field, at itakda ang Lens Ortho Size na parameter sa 4.
Bukod pa rito, kakailanganin namin ng isa pang bahagi upang tukuyin ang offset ng camera na nauugnay sa karakter — CinemachineCameraOffset
. Itakda ang Y value sa 1.5 at ang Z value sa -15.
Ngayon, subukan natin kung paano sinusundan ng camera ang ating karakter.
Sa tingin ko ito ay naging maayos. Napansin kong bahagyang nauutal paminsan-minsan ang camera. Upang ayusin ito, itinakda ko ang field ng Blend Update Method ng object ng Main Camera sa FixedUpdate.
Subukan natin ang na-update na mekanika. Subukang tumakbo at patuloy na tumalon. Maaaring mapansin ng mga nakaranasang manlalaro na ang mga pagtalon ay hindi palaging nakarehistro. Sa karamihan ng mga laro, hindi ito isang isyu.
Lumalabas na mahirap hulaan ang eksaktong oras ng landing upang pindutin muli ang jump button. Kailangan nating gawing mas mapagpatawad ang laro sa pamamagitan ng pagpayag sa mga manlalaro na pindutin nang bahagya ang pagtalon bago lumapag at agad na tumalon ang karakter sa landing. Ang pag-uugali na ito ay naaayon sa kung ano ang nakasanayan ng mga manlalaro.
Upang ipatupad ito, magpapakilala kami ng bagong variable, _jumpActionTime
, na kumakatawan sa palugit ng oras kung saan maaari pa ring ma-trigger ang isang pagtalon kung may pagkakataon.
// CharacterController.cs [Min(0)] [SerializeField] private float _jumpActionTime = 0.1f;
Nagdagdag ako ng field _jumpActionEndTime
, na minarkahan ang pagtatapos ng window ng jump action. Sa madaling salita, hanggang sa maabot ang _jumpActionEndTime
, tatalon ang karakter kung may pagkakataon. I-update din natin ang Jump
action handler.
// CharacterController.cs private float _jumpActionEndTime; public void OnJump(InputAction.CallbackContext context) { if (context.started) { if (_characterBody.State == CharacterState.Grounded) { Jump(); } else { _jumpActionEndTime = Time.unscaledTime + _jumpActionTime; } } else if (context.canceled) { StopJumping(); } }
Kapag pinindot ang jump button, kung ang karakter ay nasa lupa, agad silang tumalon. Kung hindi, iniimbak namin ang window ng oras kung saan maaari pa ring maisagawa ang pagtalon.
Alisin natin ang Grounded
state check sa mismong paraan Jump
.
// CharacterController.cs private void Jump() { _isJumping = true; _characterBody.Jump(_jumpSpeed); }
Iangkop din natin ang paraan ng paghinto sa pagtalon. Kung inilabas ang button bago lumapag, walang pagtalon na dapat mangyari, kaya ni-reset namin _jumpActionEndTime
.
// CharacterController.cs private void StopJumping() { _jumpActionEndTime = 0; //... }
Kailan natin dapat suriin na ang karakter ay nakarating at nag-trigger ng isang pagtalon? Ang estado CharacterBody
ay pinoproseso sa FixedUpdate
, habang ang pagpoproseso ng aksyon ay nangyayari sa ibang pagkakataon. Hindi alintana kung ito ay Update
o FixedUpdate
, ang isang one-frame na pagkaantala sa pagitan ng landing at jumping ay maaaring mangyari, na kapansin-pansin.
Magdaragdag kami ng isang StateChanged
na kaganapan sa CharacterBody
upang tumugon kaagad sa landing. Ang unang argumento ay ang nakaraang estado, at ang pangalawa ay ang kasalukuyang estado.
// CharacterBody.cs public event Action<CharacterState, CharacterState> StateChanged;
Isasaayos namin ang pamamahala ng estado upang ma-trigger ang kaganapan ng pagbabago ng estado at muling isusulat FixedUpdate
.
// CharacterBody.cs [field: SerializeField] private CharacterState _state; public CharacterState State { get => _state; private set { if (_state != value) { var previousState = _state; _state = value; StateChanged?.Invoke(previousState, value); } } }
Pino ko rin kung paano pinangangasiwaan surfaceHit
sa FixedUpdate
.
// CharacterBody.cs private void FixedUpdate() { //... if (_velocity.y <= 0 && slideResults.surfaceHit) { var surfaceHit = slideResults.surfaceHit; Velocity = ClipVector(_velocity, surfaceHit.normal); if (surfaceHit.normal.y >= _minGroundVertical) { State = CharacterState.Grounded; return; } } State = CharacterState.Airborne; }
Sa CharacterController
, magsu-subscribe kami sa StateChanged
event at magdagdag ng handler.
// CharacterController.cs private void OnEnable() { _characterBody.StateChanged += OnStateChanged; } private void OnDisable() { _characterBody.StateChanged -= OnStateChanged; } private void OnStateChanged(CharacterState previousState, CharacterState state) { if (state == CharacterState.Grounded) { OnGrounded(); } }
Aalisin namin ang Grounded
state check mula sa Update
at ililipat ito sa OnGrounded
.
// CharacterController.cs private void Update() { _characterBody.SetLocomotionVelocity(_locomotionVelocity); } private void OnGrounded() { _isJumping = false; }
Ngayon, idagdag ang code upang suriin kung ang isang pagtalon ay dapat ma-trigger.
// CharacterController.cs private void OnGrounded() { _isJumping = false; if (_jumpActionEndTime > Time.unscaledTime) { _jumpActionEndTime = 0; Jump(); } }
Kung _jumpActionEndTime
ay mas malaki kaysa sa kasalukuyang oras, nangangahulugan ito na ang jump button ay pinindot kamakailan, kaya ni-reset namin _jumpActionEndTime
at isagawa ang pagtalon.
Ngayon, subukang patuloy na tumalon kasama ang karakter. Mapapansin mong mas tumutugon ang jump button, at nagiging mas maayos ang pagkontrol sa karakter. Gayunpaman, napansin ko na sa ilang partikular na sitwasyon, tulad ng sulok na ipinapakita sa ilustrasyon sa ibaba, ang Grounded
na estado ay nakakaranas ng bahagyang pagkaantala, na nakakaabala sa jump chain.
Upang matugunan ito, itinakda ko ang field ng Surface Anchor
sa bahagi ng CharacterBody
sa 0.05 sa halip na 0.01. Kinakatawan ng value na ito ang pinakamababang distansya sa isang surface para makapasok ang katawan sa Grounded
na estado.
Maaaring napansin mo na ang pagtatangkang tumalon habang tumatakbo sa mga patayong ibabaw ay hindi palaging gumagana. Pakiramdam nito ay hindi tumutugon ang jump button kung minsan.
Ito ay isa sa mga subtleties ng pagbuo ng isang Character Controller para sa 2D platformers. Ang mga manlalaro ay nangangailangan ng kakayahang tumalon kahit na sila ay bahagyang huli sa pagpindot sa pindutan ng pagtalon. Bagama't tila kakaiba ang konseptong ito, ito ay kung paano gumagana ang karamihan sa mga platformer. Ang resulta ay isang character na lumilitaw upang itulak ang hangin, tulad ng ipinakita sa animation sa ibaba.
Ipatupad natin itong mekaniko. Magpapakilala kami ng bagong field upang iimbak ang window ng oras (sa mga segundo) kung saan maaari pa ring tumalon ang karakter pagkatapos mawala ang Grounded
na estado.
// CharacterController.cs [Min(0)] [SerializeField] private float _rememberGroundTime = 0.1f;
Magdaragdag din kami ng isa pang field para iimbak ang timestamp kung saan ang Grounded
na estado ay "nakalimutan."
// CharacterController.cs private float _lostGroundTime;
Ang estadong ito ay susubaybayan gamit ang kaganapang CharacterBody
. Aayusin namin ang OnStateChanged
handler para sa layuning ito.
// CharacterController.cs private void OnStateChanged(CharacterState previousState, CharacterState state) { if (state == CharacterState.Grounded) { OnGrounded(); } else if (previousState == CharacterState.Grounded) { _lostGroundTime = Time.unscaledTime + _rememberGroundTime; } }
Mahalagang tukuyin kung ang karakter ay nawala sa Grounded
na estado dahil sa isang sinadyang pagtalon o sa ibang dahilan. Mayroon na kaming flag _isJumping
, na hindi pinagana sa tuwing tatawagin StopJumping
upang maiwasan ang mga paulit-ulit na pagkilos.
Nagpasya akong huwag nang magpakilala ng isa pang flag dahil hindi makakaapekto sa gameplay ang paulit-ulit na pagkansela ng jump. Huwag mag-atubiling mag-eksperimento. Ang watawat _isJumping
ay aalisin lamang kapag ang karakter ay lumapag pagkatapos tumalon. I-update natin ang code nang naaayon.
// CharacterController.cs private void StopJumping() { _jumpActionEndTime = 0; var velocity = _characterBody.Velocity; if (_isJumping && velocity.y > 0) { _characterBody.Velocity = new Vector2( velocity.x, velocity.y / _stopJumpFactor); } }
Sa wakas, babaguhin namin ang paraan OnJump
.
// CharacterController.cs public void OnJump(InputAction.CallbackContext context) { if (context.started) { if (_characterBody.State == CharacterState.Grounded || (!_isJumping && _lostGroundTime > Time.unscaledTime)) { Jump(); } else { _jumpActionEndTime = Time.unscaledTime + _jumpActionTime; } } else if (context.canceled) { StopJumping(); } }
Ngayon, ang pagtalon sa mga patayong ibabaw ay hindi na nakakaabala sa ritmo ng gameplay at mas natural ang pakiramdam, sa kabila ng maliwanag na kahangalan nito. Ang karakter ay maaaring literal na itulak ang hangin, na lumalayo sa tila lohikal. Ngunit ito mismo ang kailangan para sa aming platformer.
Ang huling pagpindot ay ang pagharap sa karakter sa direksyon ng paggalaw. Ipapatupad namin ito sa pinakasimpleng paraan — sa pamamagitan ng pagbabago ng sukat ng character sa x-axis. Ang pagtatakda ng negatibong halaga ay magpapaharap sa ating kapitan sa kabilang direksyon.
Una, itabi natin ang orihinal na sukat kung sakaling iba ito sa 1.
// CharacterController.cs public class CharacterController : MonoBehaviour { //... private Vector3 _originalScale; private void Awake() { //... _originalScale = transform.localScale; } }
Ngayon, kapag gumagalaw pakaliwa o kanan, maglalapat kami ng positibo o negatibong sukat.
// CharacterController.cs public class CharacterController : MonoBehaviour { public void OnMove(InputAction.CallbackContext context) { //... // Change character's direction. if (value.x != 0) { var scale = _originalScale; scale.x = value.x > 0 ? _originalScale.x : -_originalScale.x; transform.localScale = scale; } } }
Subukan natin ang resulta.
Ang artikulong ito ay naging medyo detalyado, ngunit nagawa naming saklawin ang lahat ng mahahalagang aspeto ng kontrol ng character sa isang 2D platformer. Bilang paalala, maaari mong tingnan ang huling resulta sa sangay ng " Character Controller " ng repositoryo.
Kung nasiyahan ka o natagpuan mo ito at ang nakaraang artikulo ay kapaki-pakinabang, gusto ko ang mga gusto at mga bituin sa GitHub. Huwag mag-atubiling makipag-ugnayan kung makakatagpo ka ng anumang mga isyu o makakita ng mga pagkakamali. Salamat sa iyong pansin!