Quando devo usar velocidade versus addForce ao lidar com objetos de jogador?

18

Estou confuso sobre esses dois métodos na estrutura do Unity. Ambos fazem o objeto jogador se mover, parar, mudar de direção etc. Quando um deve ser usado sobre o outro e quando é apropriado?

Robert
fonte
@ Byte56 ambas as perguntas estão perguntando sobre coisas diferentes
Robert
1
Diferente, mas relacionado. É por isso que eles estão vinculados e não duplicados. Mostre que aparece na coluna vinculada à direita.
MichaelHouse

Respostas:

13

Você usaria velocitypara mover o objeto a uma taxa constante (por exemplo, uma bala) e AddForce()adicionar movimento (por exemplo, um propulsor de nave espacial). Observe também que existem dois "tipos" de movimento; força e impulso. Para um propulsor de espaçonave, você usaria impulso.

trojanfoe
fonte
4
Você pode descrever por que prefere impulsos para um propulsor de espaçonave? Na verdade, pode ser um ajuste não ideal se você estiver aplicando uma aceleração gradual ao longo do tempo, em vez de alterações instantâneas no momento devido a coisas como impactos de armas. Aplicado em uma janela de tempo, geralmente você deseja força (ou aceleração, se não quiser que a massa seja um fator) e instantaneamente usaria impulso (ou, correspondentemente, velocityChange)
DMGregory
@DMGregory Sim, depende do tipo de força que você deseja adicionar. No meu exemplo do propulsor da espaçonave, que é uma explosão momentânea de energia, o impulso é a escolha correta.
trojanfoe
2
Não ficou claro imediatamente se você quis dizer um disparo curto de um jato de atitude ou a queima contínua de um motor principal ("propulsor" é usado um pouco genericamente em ficção científica às vezes), então pensei em esclarecer para que alguém não tente usando impulsos para um foguete. ;)
DMGregory
@DMGregory De fato; minha terminologia espaço tecnologia é amplamente baseado em filmes :)
trojanfoe
@trojanfoe Vá jogar KSP. Como agora mesmo.
user253751
21

Embora já exista uma resposta aceita, acho que há alguns detalhes adicionais que merecem ser abordados.

Usando Velocity

Quando você define a velocidade, está substituindo absolutamente tudo o mais que possa afetar o movimento desse objeto. Em algumas situações, isso é desejável, como definir a velocidade inicial de uma bala uma vez no momento em que é disparada, como no exemplo de trojanfoe. Apenas tenha cuidado, pois quando usado em situações erradas, pode causar problemas:

  • Se várias fontes / scripts tentam modificar a mesma velocidade do corpo rígido, definindo-a diretamente (ie. body.velocity = foo), O que for executado por último vence e os outros têm efeito zero. Isso pode levar à ordem dos bugs de atualização, em particular fazendo com que as entidades passem ou caiam lentamente (porque a aceleração descendente devido à gravidade é substituída antes que ela se acumule)

  • Se você estiver definindo a velocidade em cada quadro, as colisões com outros objetos podem ser um pouco estranhas. É como se seu objeto estivesse sendo impulsionado por um mecanismo com torque infinito - não importa quanta velocidade ele perca em um impacto, ele volte à velocidade máxima no próximo passo da física, e sua velocidade não será desviada do impacto . Isso pode levar ao lançamento de objetos com os quais você colide, ou objetos pequenos sendo capazes de empurrar objetos enormes com muito mais facilidade do que parece, ou objetos deslizando lentamente ao longo de barreiras estáticas, em vez de desviar-se deles / delas.

Ambos os efeitos podem ser desejados algumas vezes. Por exemplo, quando estou criando jogos Kinect e quero que os membros do avatar virtual do jogador possam interagir com a cena da física, geralmente movo esses corpos usando a configuração de velocidade direta. Como a mão real do jogador está em um local conhecido e não diminuiu a velocidade da colisão com esse objeto virtual, a mão virtual precisa fazer o mesmo para permanecer alinhada; portanto, nesse caso, queremos substituir todos os outros efeitos físicos para chegue lá.

AddForce e Amigos

As funções auxiliares AddForce e similares, por outro lado, são feitas para cooperar com tudo o que acontece no mundo da física. Se várias fontes / scripts AddForce a um Rigidbody, todos esses efeitos são somados para criar uma mudança líquida no movimento do objeto (que, dependendo de como é calculado, também pode ser independente da ordem). Isso ajuda a evitar que um script atinja completamente outros efeitos físicos.

O AddForce vem em quatro tipos, especificando o parâmetro ForceMode opcional , que é útil para coisas diferentes:

ForceMode       |   Use
-----------------------------------------------------------------------
Force (default) |   Accelerate an object over 1 time step, based on its mass.
                |   Units: Newtons = kg * m/s^2
                |
Acceleration    |   Accelerate an object over 1 time step, ignoring its mass. (like gravity)
                |   Units: m/s^2
                |
Impulse         |   Instantaneously propel an object, based on its mass
                |   Units: N * s = kg * m/s
                |
VelocityChange  |   Instantaneously propel an object, ignoring its mass
                |   (like body.velocity = foo, except multiple scripts can stack)
                |   Units:  m/s

Se você está tentando modelar um impulso contínuo ao longo do tempo (por exemplo, algo que você está aplicando a cada FixedUpdate), como dirigir um carro ou queimar um foguete ou uma gravidade bem puxada, você quer Força ou Aceleração. (Dependendo se você deseja que objetos pesados ​​acelerem mais lentamente)

Se você está modelando uma mudança brusca e repentina de movimento, como disparar uma bala, recuar de uma explosão ou saltar de uma barreira, é mais provável que você queira Impulse ou VelocityChange.

O uso do AddForce ajuda a obter mais realismo físico, mas também pode exigir que você gaste mais tempo pensando na física do seu comportamento. Por exemplo, se você deseja que seu corpo tenha uma aceleração finita até uma velocidade alvo, para que ele reaja de maneira mais realista a colisões do que definir a velocidade de cada quadro, provavelmente desejará um cálculo semelhante a esta função auxiliar:

public static void AccelerateTo(this Rigidbody body, Vector3 targetVelocity, float maxAccel)
{
    Vector3 deltaV = targetVelocity - body.velocity;
    Vector3 accel = deltaV/Time.deltaTime;

    if(accel.sqrMagnitude > maxAccel * maxAccel)
        accel = accel.normalized * maxAccel;

    body.AddForce(accel, ForceMode.Acceleration);
}

A razão pela qual chamo todas essas "funções auxiliares" é que tecnicamente você pode atingir as mesmas finalidades com:

 body.velocity += suitablyCalculatedDeltaV;

( Eu acho . É possível que os resolvedores físicos baseados em PhysX / Box2D da Unity resolvam as alterações no buffer através do AddForce separadamente, mas não vi conseqüências óbvias disso)

Portanto, no final do dia, o que essas funções realmente nos atraem é a clareza de intenção . Quando quero aplicar uma força gradual, não preciso me lembrar de multiplicar meu deltaV por Time.deltaTime e dividir por massa, apenas digo que quero o ForceMode.Force e ele é tratado de maneira correta e consistente. E quando eu ou outra pessoa repetir o código mais tarde, fica imediatamente claro o que eu quis dizer, sem precisar decodificar o tempo e os cálculos em massa para descobrir isso.

DMGregory
fonte
6

Além da resposta de trojanfoe , Angry Birds vs Car Racing. Dois exemplos principais e diferentes desses métodos ( AddForcee velocityrespectivamente). Por exemplo, no Angry Birds, o uso da velocidade é um pouco mais difícil, pois você teria que definir a trajetória do projétil por si próprio, como,

Quando eu uso o AddForce no Angry Birds, eu usava,

_birdRigidbody.AddForce(new Vector2(5,5));

Enquanto que quando eu uso velocidade, eu lida com a trajetória usando

x = v*t*Cos(theta) y = v*t*Sin(theta) - 0.5 * g * t *t

Ou algo parecido com isto.

Enquanto estiver no jogo Car Racing, você terá que controlar a velocidade o tempo todo, não como o Angry Birds, ou seja, Shoot e tudo. Portanto, nesse cenário, o identificador velocityé mais útil que AddForce.

Espero que você entenda. Pelo menos um pouco.

Hamza Hasan
fonte
1
Seu exemplo do AngryBirds provavelmente deve usar uma mudança instantânea no momento (por exemplo, Impulse ou VelocityChange) quando o estilingue for lançado, em vez do ForceMode.Force padrão que simula seu efeito em uma janela de tempo. Você pode ajustar os números para obter um comportamento equivalente em qualquer uma das abordagens, mas se você alterar o passo de tempo fixo, a solução de força terá uma saída diferente (já que está integrando a força por um intervalo de tempo mais longo ou mais curto) enquanto o impulso permanece consistente como desejado, porque representa apenas o momento do lançamento.
DMGregory
0

Rigidbody Velocity e Rigidbody Addforce são duas funções confusas no Unity 3D e, frequentemente, os iniciantes não conseguem entender sua diferença. Neste artigo, discutiremos a diferença entre RigidBody.velocity e RigidBody.addforce.

Nos dois casos, seja Addforce ou função de velocidade, usaremos o termo force para explicá-los.

Quando estamos usando Rigidbody.velocity, nesse caso, estamos adicionando força ao nosso objeto, mas essa força só moverá o objeto, a menos e até que continuemos aplicando força.

Por exemplo

body.velocity = novo Vector3 (0,0,5);

Digamos que você tenha adicionado 5f na posição z e essa força será adicionada quando você pressionar a tecla W. Então, quando você pressionar a tecla W, o objeto iniciará instantaneamente na velocidade de 5. É o mesmo se você estiver adicionando força usando esta função em um carro, esse carro começará na velocidade de 5.

body.velocity = novo Vector3 (0,0,200);

E se você permitir, altere o valor para 200 e, depois de salvar, pressione W. O carro começará a rodar na velocidade de 200 a partir do início, o que não é possível no mundo real.

Agora, se você falar sobre Rigidbody.addforce

Continuando nosso exemplo de carro. se você adicionar a força de 200 ao carro

body.addforce (0,0.200);

O carro não começará a se mover na velocidade de 200 se pressionarmos W, mas ele começa devagar e depois aumenta suas velocidades e pára de acordo com o valor de arrastar.

Rigidbody.addforce começa devagar e depois acelera, assim como você está arrastando uma mesa pesada, primeiro você começa a empurrar a mesa, a mesa se move um pouco da sua posição, mas se você continuar empurrando a mesa, ela começará a se mover e se você sair dessa mesa, ela percorrerá uma certa distância, dependendo da superfície, e é o mesmo corpo rígido.

Você pode usar o Rigidbody.velocity, onde você deseja mover seu objeto para reagir instantaneamente, como o salto do jogador, e o resultado dessa força desaparecerá logo após o salto. Um foguete. Se você usar Rigidbody.addforce no salto, o Player / Objeto permanecerá no espaço por um tempo e depois voltará ao solo.

(fonte)

Numan Hamza
fonte
Você deve pelo menos tentar e adaptar sua mensagem para o formato de uma resposta Stack Troca :)
Vaillancourt