Как плавно перемещать объект твердого тела вверх или вниз в unity3d
Я запустил проект, и я прикрепил жесткое тело к своему плееру, чтобы применить к нему некоторую силу. Так что, когда я запускаю свой проект, то в FixedUpdate()
Функция Я прикладываю силу к игроку, чтобы перемещать его в прямом направлении. Поэтому, когда я нажимаю стрелку влево или вправо, он выполняет "наклон", что означает вращение его крыльев. Но теперь я хочу плавно перемещать игрока вверх или вниз, нажимая "Вверх" или "Вниз", и когда я нажимаю "Вверх" или "Вниз", это должно повлиять на игрока. Вот мой код. Пожалуйста, помогите мне.:(
void FixedUpdate ()
{
rb.AddForce(transform.forward *1000f);
float movedir = Input.GetAxis ("Horizontal");
Vector3 movement = new Vector3 (movedir, 0.0f, 0.0f);
rb.velocity = movement * movingspeed;
rb.rotation = Quaternion.Euler (0.0f, 0.0f, rb.velocity.x * -3f);//perform tilt
if (Input.GetKeyDown (KeyCode.UpArrow))
{
//code for smoothly move up from current position to = current position + 2f
}
if (Input.GetKeyDown (KeyCode.DownArrow))
{
//code for smoothly move down from current position to = current position - 2f
}
}
1 ответ
Ваш вопрос не совсем понятен. Переехать smoothly
может означать много вещей.
В общем, вы должны использовать RigidBody.MovePosition и Rigidbody.MoveRotation, чтобы установить Rigidbody
трансформируется вместо rb.rotation
а также rb.position
чтобы получить "плавные" движения:
Используйте Rigidbody.MovePosition для перемещения Rigidbody в соответствии с настройкой интерполяции Rigidbody.
Если на Rigidbody включена интерполяция Rigidbody, вызов Rigidbody.MovePosition приводит к плавному переходу между двумя позициями в любых визуализированных промежуточных кадрах. Это следует использовать, если вы хотите непрерывно перемещать твердое тело в каждом FixedUpdate.
Вместо этого установите Rigidbody.position, если вы хотите телепортировать твёрдое тело из одной позиции в другую без промежуточных позиций.
Так что, как вы можете видеть, в зависимости от ваших настроек, используя Rigidbody.MovePosition
может уже привести к "плавному" движению.
rb.MovePosition(transform.position + Vector3.up * 2.0f);
Также вы используете Input.GetKeyDown
так что он работает как триггер... он не называется непрерывно, как Input.GetKey
Если вы хотите непрерывно двигаться, пока клавиша остается нажатой, используйте, например,
// set e.g. in the inspector
public float verticalMoveSpeed;
// ...
if (Input.GetKey(KeyCode.UpArrow))
{
rb.MovePosition(transform.position + Vector3.up * verticalMoveSpeed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.DownArrow))
{
rb.MovePosition(transform.position - Vector3.up * verticalMoveSpeed * Time.deltaTime);
}
Если вы хотите запустить движение только с GetKeyDown
вместо этого вы могли бы сделать что-то вроде, например,
// set e.g. in the inspector
public float verticalMoveSpeed;
// ...
if (Input.GetKeyDown(KeyCode.UpArrow))
{
StartCoroutine(MoveVertical(2.0f, verticalMoveSpeed));
}
else if (Input.GetKeyDown(KeyCode.DownArrow))
{
StartCoroutine(MoveVertical(-2.0f, verticalMoveSpeed));
}
// ...
private IEnumerator MoveVertical(float distance, float speed)
{
var originalY = transform.position.y;
var targetY = originalY + distance;
var currentY = originalY;
do
{
rb.MovePosition(new Vector 3(transform.position.x, currentY, transform.positiom.z);
// Update currentY to the next Y position
currentY = Mathf.Clamp(currentY + speed * Time.deltaTime, originalY, targetY);
yield return null;
}
while(currentY < originalY);
// make sure you didn't move to much on Y
rb.MovePosition(new Vector3(transform.position.x, targetY, transform.position,z));
}
Чем есть два варианта предотвращения одновременных процедур:
использовать флаг. Это также препятствует прерыванию / вызову процедуры / вызову одновременно
privtae bool isMovingVertical; // ... if (Input.GetKeyDown(KeyCode.UpArrow) && !isMovingVertical ) { StartCoroutine(MoveVertical(2.0f, verticalMoveSpeed)); } else if (Input.GetKeyDown(KeyCode.DownArrow) && !isMovingVertical ) { StartCoroutine(MoveVertical(-2.0f, verticalMoveSpeed)); } // ... private IEnumerator MoveVertical(float distance, float speed) { isMovingVertical = true; // ... isMovingVertical = false; }
использование
StopAllCoroutines
прервать бегущую процедуру (внимание может привести к "бесконечным" движениям в одном направлении - по крайней мере, если вы не предотвратите это дополнительными проверками)if (Input.GetKeyDown(KeyCode.UpArrow)) { StopAllCoroutines(); StartCoroutine(MoveVertical(2.0f, verticalMoveSpeed)); } if (Input.GetKeyDown(KeyCode.DownArrow)) { StopAllCoroutines(); StartCoroutine(MoveVertical(-2.0f, verticalMoveSpeed)); }