Imparare UnityPrincipianti

I RigidBody

Altro elemento molto importante.

Si tratta di un componente necessario a tutti quegli oggetti che verranno influenzati dalla fisica. Senza di un rigidbody un oggetto non sarà influenzato dalla gravità o da altri tipi di forze come le forze generate dalle collisioni da parte di altri oggetti.

Gli oggetti che posseggono solo un collider senza la presenza di un rigidbody,  a seguito di un urto non si muoveranno.

Questo va bene per pavimenti, muri ed oggetti che possiedono un volume non "attraversabile" e per questo devono comunque avere dei colliders ma senza mai vuoversi.
Mentre per personaggi, automobili ecc.. l’aggiunta di un rigidbody permette di ricevere urti da altri colliders (con o sena rigidBody) e di comportarsi di conseguenza, muovendosi a seguito di spinte reali  senza il bisogno di preoccuparsi di modificare direttamente le posizioni del Transform da codice. Infatti i movimenti avverranno in modo realistico in base alla fisica di Unity. Ovviamente un gameObject con un rigidBody dovrà possedere sempre un collider.

I parametri da impostare sul rigidBody sono piuttosto intuibili:

  • Mass è ovviante la massa dell'oggetto, maggiore sarà la massa e maggiore sarà la forza necessaria per muoverlo.
  • Drag è la resistenza che l'oggetto oppone al movimento.
  • Angular Drag rappresenta la resistenza che oppone l'oggetto alla rotazione.
  • Use Gravity imposta se l'oggetto sarà influenzato dalla gravità.
  • Is Kinematic fa in modo che il rigidBody, se pur presente, non risenta delle forze esterne, in pratica lo rende statico.

Un rigidbody, oltre alla reazione alla fisica e alla gravità, dà la possibilità di simulare un attrito (friction) nelle collisioni con gli altri oggetti, ed una resistenza al movimento (drag) che può essere usata per molti scopi, fra cui simulare l'attrito con l’aria.

Nota: per avere una simulazione fisica realistica dovremmo stare attenti ad usare una corretta scala degli oggetti tenendo presente che un'unità di Unity rappresenta un metro. Per esempio, una corretta scala di un'automobile dovrà essere tra le 3 e le 4 unità di lunghezza, un personaggio tra le 1.5 e le 2 unità di altezza e così via. Valori molto diversi portano a simulazioni imprecise e poco ottimizzate.

Perché l’oggetto si muova a seguito di un input del giocatore, si possono usare alcuni metodi della classe rigidBody che permettono di applicare una spinta all’oggetto alla pressione di un tasto.
Quanto la spinta influenzi l’oggetto è una risultante di diversi fattori:
la sua massa, il suo drag (attrito con l'aria) e la sua frizione (attrito con altri oggetti).

Il metodo più importante della classe rigidBody è sicuramente AddForce con la quale potremmo dare una spinta all'oggetto.
Questo metodo accetta due parametri: 

  • un Vector3 (force) che indica direzione e forza della spinta (un vettore forza)
  • e uno di tipo ForceMode che indica in tipo di spinta da assegnare all'oggetto.

Il ForceMode può avere quattro tipologie che si dividono in continuative o d'impulso e che prendono in considerazione la massa oppure la ignorano:

  1. Acceleration (dà una spinta continuativa, ignorando la massa del rigidBody )
  2. Force (dà una spinta continuativa, tenendo conto della massa del rigidBody )
  3. Impulse (dà una singola forza d'impulso, tenendo conto della massa del rigidBody , utile per esempio nelle forze d'esplosione)
  4. VelocityChange (dà una singola forza d'impulso, ignorando la massa del rigidBody, utile per esempio se si vuol dare una forza a molti oggetti come astronavi che devono procedere tutte alla stessa velocità a prescindere dalla massa.)

Ricordiamoci che le forze continuative come Force e Accleration devono essere sempre usate all'interno del FixedUpdate mentre le forze d'impulso come Impulse e VelocityChange vanno usate nel normale Update.

   public int speed = 5; //La velocità
   Rigidbody myRigidBody; //Il mio rigidBody, NOTA: non serve che sia pubblico
   
   
   
   void Start(){
   //Allo Start prendo il rigidBody dal gameObject
   //così da poterci lavorare in seguito
    myRigidBody = GetComponent<Rigidbody>();
    
}

 void FixedUpdate()
{

 
 //Premendo il tasto della freccia sinistra, dai una forza uguale a "speed" verso sinistra
    if(Input.GetKey(KeyCode.LeftArrow))
    {
        myRigidBody.AddForce(Vector3.left * speed, ForceMode.Force);
    }
  //Premendo il tasto della freccia destra, dai una forza uguale a "speed" verso destra
    if(Input.GetKey(KeyCode.RightArrow))
    {
        myRigidBody.AddForce(Vector3.right * speed, ForceMode.Force);
    }

}

In realtà, per fare una cosa più corretta e non rischiare di "perdere" qualche impulso dell'utente, anche la rilevazione della pressione di un tasto andrebbe effettuata nell'Update.
Uno script più corretto per applicare il movimento ad un personaggio sarebbe tipo:

public class Move : MonoBehaviour
{
    //Creaimo una variabile che varia a seconda dell'input
    public float destraSinistraInput = 0;
    //Creiamo una variabile per la velocità
    public float velocita = 10;
    //Creiamo una variabile per la forza del salto
    public float forzaSalto = 100;
    //Il mio rigidBody su cui applicare le forze
    Rigidbody myRigidBody;
    
    void Start(){
   //Allo Start prendo il rigidBody dal gameObject
   //così da poterci lavorare in seguito
    myRigidBody = GetComponent<Rigidbody>();
    
}
 
     void Update()
    {
        //Se viene premuto il tasto Left
        if(Input.GetKey(KeyCode.LeftArrow))
        {
            //La variabile destraSinistraInput diventa 1
            destraSinistraInput = 1;
            
        }//Se viene premuto il tasto Right
        else if(Input.GetKey(KeyCode.RightArrow))
        {
            //La variabile destraSinistraInput diventa -1
            destraSinistraInput = -1;
            
        }//Se invece non viene premuto ne il tasto Left ne il tasto Right
        else
        {
            //La variabile destraSinistraInput diventa 0
            destraSinistraInput = 0;
        }
 
        if(Input.GetKeyDown(KeyCode.Space))
        {
            //Diamo la forza del salto direttamente nell'update
            myRigidBody.AddForce(Vector3.up * forzaSalto, ForceMode.Impulse);
        }
    }
 
     void FixedUpdate()
    {
        //Applica la forza solo se destraSinistraInput è diversa da 0
        if(destraSinistraInput != 0)
        {
            //Diamo la forza destra/sinistra moltiplicata per "destraSinistraInput" che può essere 1 o -1
            myRigidBody.AddForce(Vector3.left * velocita * destraSinistraInput, ForceMode.Force);
        }
    }
}

 

Ricordiamoci che Vector3.left vuol dire Vector3 (-1, 0, 0) così come Vector3.right equivale a Vector3 (1, 0, 0) .

In questo modo, quando la variabile destraSinistraInput sarà = 1, il movimento verso sinistra (Vector3.Left) sarà moltiplicato per 1 e dunque sarà "normale" movimento verso sinistra..
Mentre quando destraSinistraInput sarà = -1, il movimento sarà invertito.

7 pensieri su “I RigidBody

    1. Ciao Allanon83.
      che significa “non funziona”? Potresti essere più specifico? Che tipo di errore ti dà?
      La versione di Visual Studio non influisce e dovrebbe funzionare anche a prescindere dalla versione di Unity visto che in questo caso il codice molto semplice.

        1. Hai perfettamente ragione! E’ stata una mia svista. 😉
          In effetti nelle ultime versioni questo modo di chiamare un rigidbody è considerato obsoleto.
          Adesso bisogna dichiarare il rigidbody come un normale componente.
          Aggiorno subito l’articolo.

  1. Non mi va questo script:
    public int speed = 5; //La velocit
    Rigidbody myRigidBody; //Il mio rigidBody, NOTA: non serve che sia pubblico

    void Start(){
    //Allo Start prendo il rigidBody dal gameObject
    //così da poterci lavorare in seguito
    myRigidBody = GetComponent();

    }

    void FixedUpdate()
    {

    //Premendo il tasto della freccia sinistra, dai una forza uguale a “speed” verso sinistra
    if(Input.GetKey(KeyCode.LeftArrow))
    {
    myRigidBody.AddForce(Vector3.left * speed, ForceMode.Force);
    }
    //Premendo il tasto della freccia destra, dai una forza uguale a “speed” verso destra
    if(Input.GetKey(KeyCode.RightArrow))
    {
    myRigidBody.AddForce(Vector3.right * speed, ForceMode.Force);
    }

    }

    mi dice: che non e stato trovato un namespace con il nome RigidBody

    1. Ciao Giuseppe.
      RigidBody non è un namespace ma una classe, per questo non lo strova.
      Questo script si trova dentro ad una classe?
      Tipo:

      using UnityEngine;
      using System.Collections;
      using System;

      public class NomeScript: MonoBehaviour
      {

      …..codice

      }

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *