Estoy trabajando en un juego en el que el jugador puede recoger objetos usando algo como un rayo tractor y transportarlos.
Atraer el objeto hacia el centro de la viga no es difícil. Pero una vez que el objeto está lo suficientemente cerca del centro, necesito mantenerlo allí mientras el jugador se mueve, que es con lo que tengo problemas. Se me ocurren dos formas de hacerlo, y ambas tienen problemas:
Actualice la posición del objeto cada vez que cambie la posición del jugador, manteniéndolo centrado en la viga.
Actualice la velocidad del objeto para apuntar directamente hacia el centro del haz, cuanto más lejos, más velocidad.
Mover y rotar funciona bien con ambos enfoques, pero la física es incorrecta cuando el objeto transportado choca con otros objetos:
Con el primer enfoque, la física se ignora por completo. El objeto transportado simplemente empuja cualquier cosa fuera del camino. Esto se debe a que los cambios de posición solo se deben realizar como parte de la física mundial, en función de la velocidad.
Con el segundo enfoque, la física básicamente se comporta como debería, pero reacciona de forma exagerada. El problema es: para mantener el objeto transportado en el centro de la viga incluso cuando gira y se mueve, necesito usar valores de alta velocidad. Entonces, una vez que el objeto transportado toca otro, obtiene demasiada velocidad de la colisión.
¿Cómo puedo implementar esto correctamente? Mi mejor suposición en este momento es ir con el segundo enfoque y agregar un manejo especial para los objetos transportados a la física mundial, reduciendo la velocidad a valores razonables para colisiones o cuando el jugador deja de transportarlos. Pero eso parece una solución poco elegante.
Editar: Agregar un pseudocódigo para ilustrar cómo funciona en este momento (ese sería el segundo enfoque anterior)
void attract_object(object, ticks) {
Vector distance = beam_center - object.center;
// If the object is not close to the beam center, attract it slowly
if (magnitude(distance) > 10) {
object.velocity += distance.normalized() * ticks * 0.1;
return;
}
// Here comes the part we're talking about. That magic 0.5 is just high enough
// that the object isn't lost while moving around. But it's still so high that
// other objects are repelled with way too much force.
object.velocity = distance * ticks * 0.5;
}
Por lo que veo, esto sucede cuando el objeto transportado empuja a otro objeto:
- El objeto transportado choca con otro objeto.
- Las velocidades de los objetos se distribuyen correctamente, por lo que el objeto transportado se aleja del centro del haz en el proceso.
- El código anterior hace que el objeto transportado regrese al centro del haz, con tanta velocidad que volverá allí rápidamente
- Cuando el objeto transportado se mueve hacia el centro del haz, la mitad de su alta velocidad se transfiere al otro objeto y lo repele violentamente. Dado que la velocidad inicial del objeto transportado parece ser sensata, puedo imaginar que los pasos 2 a 4 se repiten varias veces, lo que genera una velocidad tan alta.
Esa parece ser la causa. Sin embargo, no puedo pensar en una buena manera de solucionarlo :(
Respuestas:
Esencialmente, lo que está buscando es que el objeto 'con vigas' se comporte exactamente como si lo agarrara con las manos.
Una opción sería hacer que comparta las velocidades de aceleración a / o de la 'mano' que la sostiene en lugar de ajustar su velocidad para llenar el espacio con el centro del haz.
Digamos que el centro de la viga es la mano que sostiene. Si tu personaje gira 90 grados a su izquierda en 1 segundo, entonces la velocidad de la mano sería:
If R = length of the arm: which is the radius of the rotation circle
haz que sea el tiempo transcurrido del marco para encontrar la velocidad que debes aplicar a tu objeto. Encuentre la horizontal normal a la viga para encontrar su vector de dirección.R^2 *PI /4 would be the distance traveled over a second.
Mi punto es que no tiene que resolver problemas si intenta otras implementaciones que no lo causarán en primer lugar.
Iría a jugar con la pistola de gravedad en HL2 para obtener algo de inspiración sobre el problema, pero tengo otros planes para hoy.
EDITAR: lo siento, pensé que era para una pistola de rayos 3D, pero es esencialmente lo mismo con 2D, excepto que los ejes son diferentes (y no hay una geometría compleja)
fuente
¿Qué hay de agregar una conexión de resorte, es decir, obligar al objeto transportado a regresar a la posición de transporte en función de la distancia, pero aún así permitir que sea empujado por objetos sólidos (como paredes)?
Ajuste constantemente la velocidad del objeto transportado (cambiando la aceleración según la posición / distancia) para apuntar hacia la posición del haz del tractor (es decir, su segunda aproximación). Si el objeto se empuja demasiado lejos, suelte la conexión (y el objeto).
No estoy realmente seguro de por qué necesitarías altas velocidades. Especialmente el caso de "jugador suelta" indicaría que su velocidad de rotación puede ser demasiado alta o poco realista. Tampoco olvide cosas como la resistencia al aire y la gravedad.
Editar: Teniendo en cuenta el código actualizado, el problema es bastante trivial de encontrar:
El problema aquí es el caso en que la distancia del objeto a su posición de objetivo es constantemente demasiado grande (es decir
> 10
). Mientras esta condición sea verdadera, su velocidad simplemente aumenta una y otra vez (es decir, indefinidamente).Dos posibles soluciones para esto:
Defina una velocidad máxima:
Aplique una velocidad fija en lugar de acelerar:
Acelerar mientras está demasiado lejos definitivamente es un enfoque equivocado aquí. Una cosa sobre tirar de un resorte o una banda de goma: no importa si lo sostienes durante un segundo o un minuto. Al final se acelerará de la misma manera (considerando que no ha estado en movimiento y no hay otras fuerzas aplicadas).
fuente