Всегда вне столкновения

#c# #unity3d

Вопрос:

У меня в игре есть своего рода шипы, где сфера является «Игроком», если игрок наступит на шипы, его следует вышвырнуть из коллайдера шипов. Сейчас я использую случайный диапазон, иногда это хорошо работает, но в некоторых ситуациях это снова приводит к всплескам. Я хочу, чтобы, если мяч столкнулся с шипами, он должен был отскочить в случайную позицию, но не смог снова прыгнуть в положение шипов, как при двойном столкновении.

     public float ballBounceStrenght;
    private void OnCollisionEnter(Collision collision)
    {
        if(collision.gameObject.CompareTag("Player"))
        {
            Debug.Log("collision");
            var position = new Vector3(Random.Range(-70, 70.0f), Random.Range(90f, 90.0f), Random.Range(-70.0f, 70.0f));
            ball.AddForce(position * ballBounceStrenght);
        }
    }

 

Это код, который я использую для запуска в случайном диапазоне. Понятия не имею, должен ли я делать это так, может быть, просто исправить цифры или есть какой-то другой способ сделать это.

Ответ №1:

Я бы использовал функцию для вычисления этой позиции, чтобы избежать вертикальных шипов. Для этого вы можете использовать полярные координаты в плоскости XZ и вернуть свой новый pos обратно в декартовых координатах.

Не отлаженный код, просто для вашего вдохновения:

 //return new pos from vertical pos aviding a vertical cilinder. 
private Vector3 NewPos(
  (float x, float z) VerticalPos, 
  float radiusToAvoid, float radiusMax) {
  
  float fi = Random.Range(0f, 360f);
  float radiusApart = Random.Range(radiusToAvoid, radiusMax);
  float radomHeight = Random.Range(70,90); //according to your code y range
  
  return new Vector3(VerticalPos.x   radiusApart  * Math.Cos(fi), VerticalPos.z   radiusApart * Math.Sin(fi));
}
 

Затем вам нужно будет передать x и z в функцию:

общественный поплавковый трамплин;

 private void OnCollisionEnter(Collision collision)
{
    if(collision.gameObject.CompareTag("Player"))
    {
        Debug.Log("collision");
        var position = NewPos((transform.position.x, transform.position.z), 50f, 20f);
        ball.AddForce(position * ballBounceStrenght);
    }
}
 

Все Vector3 pos могут быть переданы вместо только x и z, так что вы также можете обрабатывать относительный y в NewPos функции. Однако я предоставил вам пример кода таким образом, чтобы очистить «псевдо вертикальный цилиндр» от шипов вдоль всей оси y (вертикальной оси), чтобы получить новое положение.

Комментарии:

1. Хорошо, имеет смысл, попытаюсь сделать это сейчас, но один быстрый вопрос: что означает «R»?

2. Я обновил псевдокод в ответе, R обозначает радиус друг от друга. Это смещение радиуса от радиуса, которого следует избегать. Радиус, которого следует избегать, — это один из псевдо вертикальных цилиндров шипов, которого следует избегать в новом pos. В обновлении , которое я назвал radiusApart , обратите внимание, что это минимум radiusToAvoid . Надеюсь, в этом есть смысл

3. Ладно, понял, написал, но происходит то же самое, в большинстве случаев все работает так, как должно, иногда он просто игнорирует все и возвращается к коллайдеру

4. Я жестко закодировал то 50 и то 20 здесь: var position = NewPos((transform.position.x, transform.position.z), 50f, 20f); . Вам нужно определить радиус ваших шипов (тот, которого следует избегать) и максимальный радиус для вашего нового pos. Как уже было сказано, предоставленный код не отлаживается и просто копируется для вставки, это для вас, чтобы понять идею и двигаться дальше к решению