Tópicos Especiais em  
Engenharia de Software (Jogos II)  
Aula 05 Física  
Edirlei Soares de Lima  
<edirlei@iprj.uerj.br>  
Unity 3D: Scripting  
A engine física da Unity fornece todos os componentes para  
simulação física realista.  
Rigidbodies  
Colliders  
Triggers  
Physics Forces e Torque  
Physics Materials  
Physics Joints  
Rigidbody  
Um Rigidbody é o principal componente que permite que um  
objeto possua um comportamento físico.  
Com um Rigidbody, o objeto irá responder imediatamente a gravidade  
e forças físicas aplicadas sobre ele.  
Adicionar um Rigidbody a um objeto: Component -> Physics -> Rigidbody  
Mass: massa do objeto em kg;  
Drag: resistência do ar;  
Angular Drag: resistência do ar;  
IsKinematic: habilita/desabilita a atuação  
da engine física no objeto;  
Colliders  
Os Colliders definem as formas dos objetos para colisões  
físicas. São invisíveis e não precisam ser exatamente iguais as  
malhas dos objetos (aproximações são mais eficiente e  
indistinguíveis durante o gameplay).  
Adicionar um Collider a um objeto:  
Component -> Physics -> (Type) Collider  
Colliders primitivos:  
Box Collider;  
Sphere Collider;  
Capsule Collider;  
Colliders  
Em casos onde Colliders compostos não são suficientemente  
precisos para representar a forma correta dos objetos, é  
possível utilizar Mesh Colliders para representar a forma  
exata da malha do objeto.  
Processo de verificação de colisão complexo.  
Não existe colisão entre Mesh Colliders (solução: ativar opção Convex).  
Colliders  
Colliders podem interagir com outros Colliders de diferentes maneiras  
dependendo da forma como os seus componentes são configurados.  
Static Collider: Um GameObject sem Rigidbody e com Collider é estático.  
Geralmente usados para o cenário. É importante que esses objetos  
permaneçam completamente parados durante e gameplay.  
Rigidbody Collider: Um GameObject com Rigidbody e com Collider é dinâmico  
e controlado pela engine física da Unity.  
Kinematic Rigidbody Collider: Um GameObject com Collider e Rigidbody  
Kinematic (propriedade) interage corretamente com outros objetos físicos  
(
pode ser movido durante o gameplay), mas não é afetado por forças físicas.  
Physics Material  
Quando Colliders interagem, as suas superfícies precisam  
simular as propriedades do material que supostamente  
representam.  
Exemplos: uma superfície de gelo é escorregadia, uma bola de  
borracha oferece mais atrito e um alto fator de elasticidade.  
Criar um novo material: Assets -> Create -> Physic Material  
Dynamic Friction: fricção usada quando o  
objeto está em movimento;  
Static Friction: fricção usada quando o  
objeto está parado;  
Bounciness: fator de elasticidade;  
Detectando Colisões por Scripts  
Quando ocorrem colisões, a Unity chama automaticamente  
funções de eventos colisão em todos scripts anexados aos  
objetos envolvidos.  
void OnCollisionEnter(Collision collisionInfo)  
void OnCollisionStay(Collision collisionInfo)  
void OnCollisionExit(Collision collisionInfo)  
Detectando Colisões por Scripts  
public class PhysicsTest : MonoBehaviour {  
void OnCollisionEnter(Collision collision){  
if (collision.gameObject.tag == "Player"){  
GetComponent<Renderer>().material.color = Color.green;  
}
}
void OnCollisionStay(Collision collision){  
if (collision.gameObject.tag == "Player"){  
GetComponent<Renderer>().material.color = Color.red;  
}
}
void OnCollisionExit(Collision collision){  
if (collision.gameObject.tag == "Player"){  
GetComponent<Renderer>().material.color = Color.blue;  
}
}
}
Triggers  
É possível detectar quando um objeto passa pela área física  
de outro objeto através de Triggers.  
Propriedade “IsTrigger nos Colliders.  
void OnTriggerEnter(Collider collisionInfo)  
void OnTriggerStay(Collider collisionInfo)  
void OnTriggerExit(Collider collisionInfo)  
Triggers  
public class PhysicsTest : MonoBehaviour {  
void OnTriggerEnter(Collider collisionInfo){  
if (collisionInfo.gameObject.tag == "Player"){  
collisionInfo.gameObject.GetComponent<Renderer>().  
material.color = Color.green;  
}
}
void OnTriggerStay(Collider collisionInfo){  
if (collisionInfo.gameObject.tag == "Player"){  
collisionInfo.gameObject.GetComponent<Renderer>().  
material.color = Color.red;  
}
}
void OnTriggerExit(Collider collisionInfo){  
if (collisionInfo.gameObject.tag == "Player"){  
collisionInfo.gameObject.GetComponent<Renderer>().  
material.color = Color.blue;  
}
}
}
Joints  
Joints são utilizados para conectar objetos  
fisicamente.  
Hinge Joint: conecta dois objetos como se eles estivesse ligados por  
uma dobradiça. Ideal para representar portas, mas também pode ser  
usado para representar correntes, pêndulos, etc.  
Spring Joint: simula a confecção de dois objetos através de um  
elástico.  
Fixed Joint: conecta dois objetos de forma fixa (semelhante a  
hierarquia).  
Character Joint: usado para criar Ragdolls.  
Configurable Joint: incorpora as configurações de todos os outros  
joints, permitindo a criação de joints personalizados.  
Character Controller  
O Character Controller é geralmente utilizado para controlar  
personagens.  
public class ControlePersonagem : MonoBehaviour {  
public float speed = 70;  
private CharacterController ch;  
void Start(){  
ch = GetComponent<CharacterController>();  
}
void Update(){  
if (Input.GetKey(KeyCode.UpArrow))  
ch.SimpleMove(transform.forward * speed * Time.deltaTime);  
if (Input.GetKey(KeyCode.DownArrow))  
ch.SimpleMove(-transform.forward * speed * Time.deltaTime);  
if (Input.GetKey(KeyCode.LeftArrow))  
transform.Rotate(Vector3.up * -speed * Time.deltaTime);  
if (Input.GetKey(KeyCode.RightArrow))  
transform.Rotate(Vector3.up * speed * Time.deltaTime);  
}
}
Forças  
É possível aplicar forças em objetos através de scripts ou  
através do componente “Constant Force”.  
Métodos do Rigidbody:  
AddForce  
AddForceAtPosition  
AddTorque  
AddExplosionForce  
AddRelativeForce  
AddRelativeTorque  
Aplicando Forças  
AddForce:  
public class PhysicsTest : MonoBehaviour {  
private Rigidbody rb;  
public float moveForce = 50;  
void Start(){  
rb = GetComponent<Rigidbody>();  
}
void FixedUpdate(){  
if (Input.GetKey(KeyCode.UpArrow))  
{
rb.AddForce(Vector3.forward * moveForce);  
}
}
}
Aplicando Forças  
AddForceAtPosition:  
public class PhysicsTest : MonoBehaviour {  
private Rigidbody rb;  
public float moveForce = 50;  
void Start(){  
rb = GetComponent<Rigidbody>();  
}
void FixedUpdate(){  
if (Input.GetKey(KeyCode.UpArrow)){  
rb.AddForceAtPosition(transform.forward * moveForce,  
new Vector3(transform.position.x,  
transform.position.y - 0.4f,  
transform.position.z));  
}
}
}
Aplicando Forças  
AddTorque:  
public class PhysicsTest : MonoBehaviour {  
private Rigidbody rb;  
public float moveForce = 50;  
void Start(){  
rb = GetComponent<Rigidbody>();  
}
void FixedUpdate(){  
if (Input.GetKey(KeyCode.UpArrow)){  
if (Input.GetKey(KeyCode.LeftArrow))  
{
rb.AddTorque(transform.up * force);  
}
}
}
}
Aplicando Forças  
AddExplosionForce :  
public class PhysicsTest : MonoBehaviour {  
public float radius = 5.0f;  
public float power = 10.0f;  
void Update(){  
if (Input.GetKeyDown(KeyCode.Space)){  
Vector3 explosionPos = transform.position;  
Collider[] colliders = Physics.OverlapSphere(explosionPos,  
radius);  
foreach (Collider hit in colliders){  
Rigidbody rb = hit.GetComponent<Rigidbody>();  
if (rb != null)  
rb.AddExplosionForce(power, explosionPos, radius, 3.0f);  
}
}
}
}