OrbitCamera пересечение с коллайдерами

Физика в Unity

OrbitCamera пересечение с коллайдерами

Сообщение 3Dragon 08 янв 2010, 01:20

Всем доброго времени суток.
Разбираю скрипт OrbitCamera из 3d Platform tutorial
Возник такой вопросик - для просчета коллизий камеры с коллайдерами используется Physics.Raycast (насколько я разобрался).
Так вот, когда камера пересекается, например, с плэйном за ней, приближение камеры к таргету "активируется" не сразу, таким образом, камера успевает наполовину зайти за поверхность плэйна. Т.е. при некоторых ракурсах игрок успевает увидеть "обратную сторону" модели.
Видимо, это происходит из-за того, что луч проводится через центр камеры и возникает ситуация, когда камера уже пересекается с объектом, а луч еще нет.
Собственно, вопрос:
Можно ли модифицировать OrbitCamera так, чтобы камера не заходила за поверхность моделей? Один из вариантов - добавить коллайдер для камеры и просчитывать его пересечения с объектами. Возможно есть более изящные варианты?

P.S. В джаваскрипте я совсем новичок, так что заранее прошу прощения если вопрос некорректен. Спасибо.

Код: Выделить всё
var target : Transform;
var distance = 4.0;

var lineOfSightMask : LayerMask = 0;
var closerSnapLag : float = 0.2;
var distanceVelocity = 0.0;

var currentDistance;
var x = 0.0;
var y = 90.0;

var yMinLimit = -20;
var yMaxLimit = 80;

function Start () {
   var angles = transform.eulerAngles;
    x = angles.y;
    y = angles.x;
   currentDistance = distance;
      if (rigidbody)
      rigidbody.freezeRotation = true;
}

function LateUpdate () {
   if (target) {
      x += Input.GetAxis("Mouse X");
        y -= Input.GetAxis("Mouse Y");
      
      y = ClampAngle(y, yMinLimit, yMaxLimit);
      
      var rotation = Quaternion.Euler(y, x, 0);
      var targetPos = target.position;
      var direction = rotation * -Vector3.forward;
      
      var targetDistance = SightLine(targetPos, direction);
      currentDistance = Mathf.SmoothDamp(currentDistance, targetDistance, distanceVelocity, closerSnapLag * .3);
      
      transform.rotation = rotation;
      transform.position = targetPos + direction * currentDistance;
   }
}

function SightLine (target : Vector3, direction : Vector3) : float
{
   var hit : RaycastHit;
   if (Physics.Raycast (target, direction, hit, distance, lineOfSightMask.value))
      return hit.distance;
   else
      return distance;
}

static function ClampAngle (angle : float, min : float, max : float)
{
   return Mathf.Clamp (angle, min, max);
}
Глаза боятся, а руки - крюки.
3Dragon
UNIт
 
Сообщения: 61
Зарегистрирован: 25 ноя 2009, 21:50
Откуда: Санкт-Петербург
  • ICQ

Re: OrbitCamera пересечение с коллайдерами

Сообщение Slava 08 янв 2010, 13:01

Вот немного подправленный скрипт Орбит камеры
Код: Выделить всё
var target : Transform;
var targetOffset = Vector3.zero;
var distance = 4.0;

var lineOfSightMask : LayerMask = 0;
var closerRadius : float = 0.2;
var closerSnapLag : float = 0.2;

var xSpeed = 200.0;
var ySpeed = 80.0;

var yMinLimit = -20;
var yMaxLimit = 80;

private var currentDistance = 10.0;
private var x = 0.0;
private var y = 0.0;
private var distanceVelocity = 0.0;

function Start () {
    var angles = transform.eulerAngles;
    x = angles.y;
    y = angles.x;
   currentDistance = distance;
   
   // Make the rigid body not change rotation
      if (rigidbody)
      rigidbody.freezeRotation = true;
}

function LateUpdate () {
    if (target) {
        x += Input.GetAxis("Mouse X") * xSpeed * 0.02;
        y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;
      
      y = ClampAngle(y, yMinLimit, yMaxLimit);
      
        var rotation = Quaternion.Euler(y, x, 0);
        var targetPos = target.position + targetOffset;
        var direction = rotation * -Vector3.forward;
      
      distance -= (Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime) * scrollSpeed * Mathf.Abs(distance);
      distance = Mathf.Clamp(distance, scrollMinLimit, scrollMaxLimit);
      
      var hit : RaycastHit;
      if (Physics.Raycast (targetPos,  direction, hit, distance + closerRadius, lineOfSightMask.value))
         currentDistance = hit.distance - closerRadius;
      else
         currentDistance = Mathf.SmoothDamp(currentDistance, distance, distanceVelocity, closerSnapLag * .3);
       
        transform.rotation = rotation;
        transform.position = targetPos + direction * currentDistance;
    }
}

static function ClampAngle (angle : float, min : float, max : float) {
   if (angle < -360)
      angle += 360;
   if (angle > 360)
      angle -= 360;
   return Mathf.Clamp (angle, min, max);
}

@script AddComponentMenu("Third Person Camera/Mouse Orbit")
Добавить slava-1234 в Skype
Slava
UNIт
 
Сообщения: 135
Зарегистрирован: 05 апр 2009, 05:14

Re: OrbitCamera пересечение с коллайдерами

Сообщение Paul Siberdt 08 янв 2010, 13:23

Я для камеры в тестах пользовал такую конструкцию:
- логический якорь камеры, скрипт камеры именно его камерой и считает
- фиксед джойнт, прикрепленный к логическому якорю
- якорь камеры (сферический коллайдер+ригидбодя), прикрепленный к фиксед джойнту
- сама камера, лерпом следующая за якорем.

Фиксед джойнт на самом деле - жесткая пружина. Его свойства очень помогают в огибаниях и обхождениях.
Столкновения не мешают скрипту считать желаемое положение камеры, но обрабатываются ригидбодей, внося поправки. Вероятно, в моих случаях не было критических и сложных коллизий и скоростей, потому я не наблюдал ляпов... :) ...да я еще не сильно глубоко копал в вопросе и для теста вполне удовлетворился "не проваливанием" камеры в другие объекты сцены.
Аватара пользователя
Paul Siberdt
Адепт
 
Сообщения: 5317
Зарегистрирован: 20 июн 2009, 21:24
Откуда: Moscow, Russia
Skype: siberdt
  • Сайт


Вернуться в PhysX

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1