Skrypt na ruch bazowany o fizykę

Modele / Skrypty / Textury / Fonty / Dźwięki / etc.

Skrypt na ruch bazowany o fizykę

Postprzez darkhog » 22 Lut 2014, 10:47

Jak użyć
Daj obiektowi który ma się ruszać CapsuleCollider (albo jakikolwiek inny collider, ale najlepiej działa z capsule) oraz rigidbody. W Constraints rigidbody ustaw Freeze Rotation na osiach x/z (co by postać się nie wywalała) i daj ten skrypt:

Kod: Zaznacz wszystko
using UnityEngine;
using System.Collections;
//Here there be dragons
public class PhysicBasedCharacterController : MonoBehaviour {
   private bool isGrounded;
   public float movementForce = 30;
   public float jumpForce=20;
   public float normalLimit =0;
   public bool parentToColliders = true;
   private bool kinematic = false;
   private bool onPlatform =false;
   private int jumping =0;
   public string[] ParentsWhiteList;
   // Use this for initialization
   void Start () {
   
   }
   public void setOnPlatform(bool op){
      onPlatform = op;
   }
   // Update is called once per frame
   void Update () {
      jumping--;
      kinematic = (!((Input.GetAxisRaw("Vertical")>0) || (Input.GetAxisRaw("Vertical")<0) || (Input.GetAxisRaw("Horizontal")>0) || (Input.GetAxisRaw("Horizontal")<0) || (Input.GetButtonDown("Jump")))) && (isGrounded);
      //we should move only if we aren't in menu
      if (!Globals.isInMenu){
         if (Input.GetAxisRaw("Vertical")>0){
            this.rigidbody.AddForce(this.transform.forward * movementForce);
         } else if (Input.GetAxisRaw("Vertical")<0){
            this.rigidbody.AddForce(-this.transform.forward * movementForce);
         }
         if (Input.GetAxisRaw("Horizontal")>0){
            this.rigidbody.AddForce(this.transform.right * movementForce);
         } else if (Input.GetAxisRaw("Horizontal")<0){
            this.rigidbody.AddForce(-this.transform.right * movementForce);
         }
         if ((isGrounded)&& (Input.GetButtonDown("Jump"))) {
            this.rigidbody.isKinematic=false;
            kinematic=false;
            isGrounded = false;
            jumping = 3;
            this.rigidbody.AddForce(this.transform.up * jumpForce);
            
         }
      }
      this.rigidbody.isKinematic=(kinematic) && (onPlatform) && (jumping<1);
   }
   void OnGUI(){
      //GUI.Box(new Rect(400,0,200,50),"isGrounded = "+isGrounded.ToString()+"\n"+"Jump = "+Input.GetButton("Jump").ToString());
   }
   void OnCollisionStay(Collision other) {
      foreach(ContactPoint temp in other.contacts) {
         if((temp.normal.y>normalLimit)) {
            isGrounded=true;
         }
         
      }
      //following is needed for moving platforms to work
      bool canParent = false;
      foreach (string name in ParentsWhiteList){
         if (other.gameObject.name == name) {canParent = true;}
      }
      if ((parentToColliders) && (isGrounded) && (canParent)){
         this.transform.parent = other.gameObject.transform;
      }
   }
   void OnCollisionExit(Collision other) {
      isGrounded=false;
      
   }
}
//No, really

//                                                                          ,###, ,###,
//                                                                        ,##\\\#,#\\\#,
//                                                                     ,###\\\\\\#\\\\\#,
//                                                                   ,##\\\\\\\\\#\\\\\\#,
//                                                                   #\\#\\\\\\\\#\\\\\\\#
//                                    ...,###########,              ,#\\\#\\\\\\\#\\\\\\\#
//                            .,##########           #             ,#\\\\#\\\\\\#\\\\\\\\\#,
//    ,                 ,#######                    #'          ,###\\\\\\##\\\#\\\\\\\\\\\##,
//    #,              ,##              #############'        ,###\\\\\\\\\\\#\\#\\\\\\\\\\\\\##,
//    ##,          ,###################'                  ,###\\\\\\\\\\\\\\\##\\\\\\\\\\\\\\\\###,
//    ###,      ,#####################'                  ,#\\\\\\\\\\\\\\\\\\#\\\\\\\\\\\\\\\\\#\\#,
//    '###,   .,#####################'               ,####\\\\\\\\\\\\\\\\\\#\\\\\\\\\\\\\\\###\\\\#
//     '###, ,#########.-.##########'          ,######\\\\\\\\\\\\\\\\\\####\\\\\\\\\\\\####\\\\\\\#
//      '###,#######  # | #  ######'        ,###\\\\\\\\\\\\\\\\\\\\\###\\\\\\\\\#######\\\\\\\\\\#'
//       ###########################,     ,##\\\\\\\\\\\\\\\\\\\\\\\#\\\\\\######\\\\\\\\\\\\\\\\\#
//   ################################  ,###\\\\\\\\\\\\\\\\\\\\\\\##\\\####\\\\\\\\\\\\\\\\\\\\\\\#
//  #%% #############################..#\\\\\\\\\\\\\\\\\\\\\\\\##\\###\\\\\\\\\\\\\\\\\\\\\\\\\##'
//   ##################################\\\\\\\\\\\\\\\\\\\\\####\\###\\\\\\\\\\\\\\\\\\\\\\\\\##'
//   ######,..............,############\\\\\\\\\\\\\\\\\####\\\###\\\\\\\\\\\\\\\\\\\\\\\\\###'
//  #,....'&%*$$@$%^&**&^@!.#############\\\\\\\\\\\\###\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\##'
//  #%&$$%^...............'################\\########\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\##'
//   #....'##################################\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\#####
//    ########################################\\\\\\\\\\\\\\\\\\\\\\\\############'
//                  ############################ #####################
//                  #\\\\\#######################
//                 #\\\\\\\\####################
//                  #\\\\\\\#################
//                   #########################
//                    #\\\\\####################
//                    #\\\\\######################
//                     #############################


Postać powinna się teraz ruszać do przodu/tyłu oraz na boki. Mogą być jednak problemy ze skokiem (albo będzie walljump, albo nie będzie można skakać). W takim wypadku odkomentuj linijkę w OnGUI i dostosuj Normal Limit w skrypcie aż w dodatkowym okienku będzie się pokazywała poprawna wartość dla isGrounded (true jeśli na ziemi, false jeśli w powietrzu). Generalnie wartość 0.59 jest dobra (testowane empirycznie jako że używam tego skryptu w mojej grze), chyba że chcesz uzyskać jakieś efekty typu walljump.

Możesz też musieć dostosować siłę aplikowaną przy ruch (movement force) i siłę skoku (jump force). Jeśli postać zdaje się przyspieszać w nieskończoność, pobaw się z Drag w rigidbody.

Jedna ważna sprawa: Możesz usunąć ifa dot. Globals.isInMenu (ale nie kod w ifie, bo postać nie będzie się ruszała!), jego zadaniem jest sprawdzanie czy postać jest w menu (pauza, rzeczy typu ekwipunek, itd.) i ruszać postacią tylko jeśli nie jest w menu.

Dlaczego używam fizyki w Unity?
Bo nie chce mi się bawić z character controllerami, strasznie trudno character controllery dostosować, a jak piszesz swój, to musisz bawić się, żeby uzyskać rzeczy jak realistyczne spadanie, a potem i tak oglądasz jak się wszystko rozpada (albo spada do góry w wypadku gdy pomyliłeś znak przy obliczaniu grawitacji). To rozwiązanie jest po prostu łatwiejsze do ustawienia niż zabawa z kontrolerami.

Licencja?
Licencja to róbta co chceta.
darkhog
 
Posty: 83
Rejestracja: 22 Lut 2014, 10:16
Has thanked: 0 time
Been thanked: 0 time

Wróć do Zasoby

Kto jest na forum

Użytkownicy przeglądający to forum: Brak zarejestrowanych użytkowników oraz 2 gości

cron