Sto lavorando a un gioco in cui il giocatore può raccogliere oggetti usando qualcosa come un raggio traente e trasportarli.
Attrarre l'oggetto verso il centro del raggio non è difficile. Ma una volta che l'oggetto è abbastanza vicino al centro, devo tenerlo lì mentre il giocatore si muove, che è ciò con cui ho problemi. Posso pensare a due modi per farlo, ed entrambi hanno problemi:
Aggiorna la posizione dell'oggetto ogni volta che cambia la posizione del giocatore, mantenendolo centrato sulla trave.
Aggiorna la velocità dell'oggetto per puntare direttamente verso il centro del raggio, più è lontano, più è la velocità.
Lo spostamento e la rotazione funzionano bene con entrambi gli approcci, ma la fisica è sbagliata quando l'oggetto trasportato si scontra con altri oggetti:
Con il primo approccio, la fisica viene completamente ignorata. L'oggetto trasportato spinge via qualsiasi cosa. Questo perché i cambiamenti di posizione dovrebbero essere fatti solo come parte della fisica mondiale, basata sulla velocità.
Con il secondo approccio, la fisica si comporta sostanzialmente come dovrebbe, ma reagisce in modo eccessivo. Il problema è: per mantenere l'oggetto trasportato al centro del raggio anche quando si ruota e si sposta, è necessario utilizzare valori di velocità elevata. Quindi, una volta che l'oggetto trasportato tocca un altro, ottiene troppa velocità dalla collisione.
Come posso implementarlo correttamente? La mia ipotesi migliore in questo momento è quella di andare con il secondo approccio e aggiungere una gestione speciale per gli oggetti trasportati alla fisica mondiale, riducendo la velocità a valori sani per le collisioni o quando il giocatore smette di trasportarli. Ma sembra una soluzione piuttosto inelegante.
Modifica: aggiunta di un pseudo codice per illustrare come funziona ora (sarebbe il secondo approccio sopra)
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;
}
Da quello che vedo, questo accade quando l'oggetto trasportato spinge via un altro oggetto:
- L'oggetto trasportato si scontra con un altro oggetto
- Le velocità degli oggetti sono distribuite correttamente, quindi l'oggetto trasportato viene allontanato dal centro del raggio nel processo
- Il codice sopra fa tornare l'oggetto trasportato al centro del raggio, con così tanta velocità che tornerà rapidamente lì
- Quando l'oggetto trasportato si sposta indietro verso il centro del raggio, metà della sua alta velocità viene trasferita all'altro oggetto, respingendolo violentemente. Poiché la velocità iniziale dell'oggetto trasportato sembra sana, posso immaginare che i passaggi da 2 a 4 vengano ripetuti più volte, aumentando così la velocità.
Questa sembra essere la causa. Non riesco a pensare a un modo carino per risolverlo però :(