(Проблема) движение на движущемся объекте

Программирование на Юнити.

(Проблема) движение на движущемся объекте

Сообщение Garu 14 авг 2010, 08:07

персонаж - переделанный PlatformerController (лишь добавка осей)
корабль - ставил аналогичную управляху, так же пробовал нечто типа - А.transform.position = Б.transform.position
при статичном положении корабля - перемещение полностью адекватна, при движении - по плоским участкам корабля бегает нормально, но ступеньки дают следующий эффект:
при набеге на них по направлению движения корабля, словно упираюсь в стену и персонажа сильно дергает вперед и назад, если бежать против движения корабля - буквально телепортирует сквозь несколько кусков корабля. ступеньки и как чайлд крепил в общей модельке, и просто куском основной части - без разницы, при наклоне, даже небольшом, начинаются проблемы с движением, к примеру если плоскость с коллизией ставлю под углом градусов в 5, при движении вперед, двигаюсь назад. Ну а дальше по возрастанию угла, все сильнее глюки. Как лучше тогда поставить физику персонажа (и\или объекта), дабы сохранить возможность перемещения по всем осям на подвижном объекте?
Аватара пользователя
Garu
UNITрон
 
Сообщения: 199
Зарегистрирован: 13 авг 2009, 18:26

Re: (Проблема) движение на движущемся объекте

Сообщение Zaicheg 14 авг 2010, 10:50

Вряд ли многие тут помнят, как работает PlatformerController. Если сможете описать проблему на уровне стандартных компонентов юнити, то вероятность решения будет выше, в том числе и я подумаю над ним.
Дьяченко Роман
e-mail: _zaicheg.reg@gmail.com
skype: zaicheg12
vkontakte: _vk.com/zaichegq
Работа: _wie3.com _www.sanviz.com
Аватара пользователя
Zaicheg
Адепт
 
Сообщения: 3024
Зарегистрирован: 19 июн 2009, 15:12
Откуда: Череповец

Re: (Проблема) движение на движущемся объекте

Сообщение Garu 14 авг 2010, 11:38

Zaicheg писал(а):Вряд ли многие тут помнят, как работает PlatformerController. Если сможете описать проблему на уровне стандартных компонентов юнити, то вероятность решения будет выше, в том числе и я подумаю над ним.

ок, тогда попробую перефразировать проблему и потребность

Есть:
Персонаж и объект, объект движется по горизонтали, на объекте есть ступеньки и разница высот. Нужно что бы персонаж свободно перемещался по данному объекту, как обычный контроллер по земле, с сохранением возможности сойти\зайти на корабль и сохранение возможности прыжка. Опробованные варианты принесли 0 эффекта.
И да, забыл сказать, очень желательно ява а не шарп, ибо с шарпом не дружу.

Вот по позиции на объекте часть:

Код: Выделить всё
if (activePlatform != null) {
      var newGlobalPlatformPoint = activePlatform.TransformPoint(activeLocalPlatformPoint);
      var moveDistance = (newGlobalPlatformPoint - activeGlobalPlatformPoint);
      transform.position = transform.position + moveDistance;
      lastPlatformVelocity = (newGlobalPlatformPoint - activeGlobalPlatformPoint) / Time.deltaTime;
   } else {
      lastPlatformVelocity = Vector3.zero;   
   }

кажись в этом проблема, но точно не уверен, по этому и залез сюда с вопросом - какой метод лучше, ну и что вообще с этим можно сотворить, дабы оно пахало как требуется.
Аватара пользователя
Garu
UNITрон
 
Сообщения: 199
Зарегистрирован: 13 авг 2009, 18:26

Re: (Проблема) движение на движущемся объекте

Сообщение Paul Siberdt 14 авг 2010, 12:32

Ниччиво не понимаю, но, вероятно, двигать персонажа лучше в LateUpdate, а все остальные элементы сцены - в обычном Update. При этом персонаж учтёт все изменения за кадр вокруг себя.
Аватара пользователя
Paul Siberdt
Адепт
 
Сообщения: 5317
Зарегистрирован: 20 июн 2009, 21:24
Откуда: Moscow, Russia
Skype: siberdt
  • Сайт

Re: (Проблема) движение на движущемся объекте

Сообщение sp00n 14 авг 2010, 12:36

Без остального кода тяжело судить, но в глаза сразу бросается строчка
transform.position = transform.position + moveDistance;
, я так понимаю moveDistance тоже вектор и тут мы имеем интересную ситуацию с векторной сумой, в результате которой персонаж и под землю уйдет и на небо взлетит, не говоря уже направо/налево. Тут дело не в шарпе или джаваскрипте, а в простом незнании векторной арифметики(гы, новый термин придумал:) ). Я могу помочь со скриптом, но нужно чуть больше информации - у тебя 2д или 3д платформер, какие ограничения по осям и все такое. Обращайся, наверное, в личку - а как сделаем, то выложим результат здесь или в исходниках :) Учить математику не направляю, так как понимаю что не твой профиль :)
Ты молод, креативен, талантлив?
Амбициозен, уверен в себе, полон свежих идей?
А делать хоть что-нибудь умеешь?!
sp00n
UNITрон
 
Сообщения: 254
Зарегистрирован: 27 фев 2010, 20:43

Re: (Проблема) движение на движущемся объекте

Сообщение Paul Siberdt 14 авг 2010, 12:49

Звиняйте, сама строчка ничего плохого в себе не несет :ymparty:
Все мои трансформы работают именно на кинетическом приращении дельты к текущей позиции :)

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

Re: (Проблема) движение на движущемся объекте

Сообщение sp00n 14 авг 2010, 13:14

Про векторную алгебру я в курсе, также как и про аналитическую геометрию :) Просто для меня это какбэ елементарные знания на уровне арифметики для школьника))))
А насчет дельты - я так помню, что в юнити идет как раз сумма векторов, а не приращение дельты. Но, даже если не так и идет приращение - то приращение по каким осям? или же просто будет x+delta_x, y+delta_y, z+delta_z? В последнем случае мы имеем проблему в том, а где это считается? В Update, FixedUpdate, LateUpdate? Как я уже говорил - тут просто недостаток информации :)
Ты молод, креативен, талантлив?
Амбициозен, уверен в себе, полон свежих идей?
А делать хоть что-нибудь умеешь?!
sp00n
UNITрон
 
Сообщения: 254
Зарегистрирован: 27 фев 2010, 20:43

Re: (Проблема) движение на движущемся объекте

Сообщение Neodrop 14 авг 2010, 14:43

Garu писал(а):персонаж - переделанный PlatformerController (лишь добавка осей)
корабль - ставил аналогичную управляху, так же пробовал нечто типа - А.transform.position = Б.transform.position
при статичном положении корабля - перемещение полностью адекватна, при движении - по плоским участкам корабля бегает нормально, но ступеньки дают следующий эффект:
при набеге на них по направлению движения корабля, словно упираюсь в стену и персонажа сильно дергает вперед и назад, если бежать против движения корабля - буквально телепортирует сквозь несколько кусков корабля. ступеньки и как чайлд крепил в общей модельке, и просто куском основной части - без разницы, при наклоне, даже небольшом, начинаются проблемы с движением, к примеру если плоскость с коллизией ставлю под углом градусов в 5, при движении вперед, двигаюсь назад. Ну а дальше по возрастанию угла, все сильнее глюки. Как лучше тогда поставить физику персонажа (и\или объекта), дабы сохранить возможность перемещения по всем осям на подвижном объекте?


Это от того, что вы двигаете объект имеющий коллайдер, но не имеющий Rigidbody - а этим вы нарушаете корректность физики. Добавьте к кораблю ригидбоди и поставьте на нём галку isKinematic
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

Re: (Проблема) движение на движущемся объекте

Сообщение Paul Siberdt 14 авг 2010, 16:10

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

Re: (Проблема) движение на движущемся объекте

Сообщение Garu 15 авг 2010, 06:00

Нео - печально но факт, ригидбоди на кораблике и так было, масса 10000 драг 0 АнДраг0.05 гравитация 0 кинематика - торчит галка, Фриз ротейшен тоже стояло, но что с ним что без него, эффект такой же...
И даже на отдельных частях уже пробовал кидать ригидбоди (не на весь кораблик, а на палубную часть с ступеньками), эффекта не получил.

Вот собственно вся управляшка, сильно не пинать - расковырял дико (мне так удобнее ковыряться) и лишняк не сносил еще (как заработает уже сделаю адекватный внешний вид)
Код: Выделить всё
var canControl = true;
var myCamera: Transform;
var me: Transform;

class PlatformerControllerMovement {
   //var walkSpeed = 3.0;

   var gravity = 60.0;
   var maxFallSpeed = 20.0;

//   var speedSmoothing = 5.0;

   var rotationSmoothing = 10.0;

   @System.NonSerialized
   var direction = Vector3.zero;

   @System.NonSerialized
   var verticalSpeed = 0.0;

   @System.NonSerialized
   var speed = 0.0;

   
   var isMoving = false;
   var isMoving2 = false;
   
   @System.NonSerialized
   var collisionFlags : CollisionFlags;

   @System.NonSerialized
   var velocity : Vector3;
   
   @System.NonSerialized
   var inAirVelocity = Vector3.zero;

   @System.NonSerialized
   var hangTime = 0.0;
}

var movement : PlatformerControllerMovement;

class PlatformerControllerJumping {

   var enabled = true;


   var height = 1.0;

   var extraHeight = 4.1;

   @System.NonSerialized
   var repeatTime = 0.05;

   @System.NonSerialized
   var timeout = 0.15;


   @System.NonSerialized
   var jumping = false;
   
   @System.NonSerialized
   var reachedApex = false;
 

   @System.NonSerialized
   var lastButtonTime = -10.0;
   

   @System.NonSerialized
   var lastTime = -1.0;


   @System.NonSerialized
   var lastStartHeight = 0.0;
}


var jump : PlatformerControllerJumping;


var R2 : float;
var J2 : float;

var bulletGUI : GUIText;

private var Weapon : WeaponQ;

private var controller : CharacterController;

// Moving platform support.
private var activePlatform : Transform;
private var activeLocalPlatformPoint : Vector3;
private var activeGlobalPlatformPoint : Vector3;
private var lastPlatformVelocity : Vector3;

// This is used to keep track of special effects in UpdateEffects ();
private var areEmittersOn = false;

var SPDrot = 1;

var Using = 0;

function Awake ()

{

   Weapon = GetComponentInChildren(WeaponQ);
   moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
      moveDirection = transform.TransformDirection(moveDirection);
   controller = GetComponent (CharacterController);
   
}

function LateUpdate ()
{   
   UpdateGUI();
   tdt3 = Time.time;
}


function UpdateGUI ()
{
if (Weapon) {
      bulletGUI.text = Weapon.GetBulletsLeft().ToString();
   }

}

function UpdateSmoothedMovementDirection ()
   {   
   var h = Input.GetAxisRaw ("Vertical");
   var g = Input.GetAxisRaw ("Horizontal");
   
   var h2 = Input.GetButton("Fire1");
   
   var Stat = GetComponent(Stat);
   var R2 = Stat.RunSpd;
if (Using < 1)
{
   if (!canControl)
      h = 0.0;
      //g = 0.0;

   movement.isMoving = (Mathf.Abs (h) > 0.1);
   //movement.isMoving2 = (g > 0.1) || (g < -0.1);
   movement.isMoving2 = (Mathf.Abs (g) > 0.1);
   lineX = (Mathf.Abs (h) > 0.1) && (Mathf.Abs (g) > 0.1);
   
   //transform.forward= myCamera.forward;
      
   if (movement.isMoving)
   {
   //transform.eulerAngles.y = myCamera.eulerAngles.y;
      movement.direction = myCamera.forward * h;
      if(h<0)
      {
      movement.direction = -myCamera.forward * h*0.5;
      }
      
   }
   
   if (movement.isMoving2)
   {
   //transform.eulerAngles.y = myCamera.eulerAngles.y;
   movement.direction = myCamera.right * g;
   
   
   //transform.rotation.y = myCamera.rotation.y;
   }
   if (lineX)
   {
   movement.direction = (myCamera.right * g + myCamera.forward * h) *0.7;
   //if (movement.direction.sqrMagnitude > 0.01)
      
   if(h<0)
      {
      //movement.direction = -(myCamera.forward * h) *0.5;
      movement.direction = -(myCamera.right * g + myCamera.forward * h) *0.4;
      }
      
   //transform.rotation.y = myCamera.rotation.y;
   }






   
   // Grounded controls
   if (controller.isGrounded) {
      // Smooth the speed based on the current target direction
      //var curSmooth = movement.speedSmoothing * Time.deltaTime;
      
      // Choose target speed
      var targetSpeed = h || Mathf.Min (Mathf.Abs(g), 1.0);
   
      // Pick speed modifier
      if (Input.GetButton ("Speed") && canControl)
      {
         targetSpeed *= 0;
         movement.isMoving = false;
         movement.isMoving2 = false;
         }
      else
         targetSpeed *= R2;

      movement.speed = Mathf.Lerp (movement.speed, targetSpeed, 1);
      
      movement.hangTime = 0.0;
   }
   else {
      // In air controls
      movement.hangTime += Time.deltaTime;
   }
   }
}

















function ApplyJumping () {
   // Prevent jumping too fast after each other
   if (jump.lastTime + jump.repeatTime > Time.time)
      return;

   if (controller.isGrounded) {
      // Jump
      // - Only when pressing the button down
      // - With a timeout so you can press the button slightly before landing      
      if (jump.enabled && Time.time < jump.lastButtonTime + jump.timeout) {
         movement.verticalSpeed = CalculateJumpVerticalSpeed (jump.height);
         movement.inAirVelocity = lastPlatformVelocity;
         SendMessage ("DidJump", SendMessageOptions.DontRequireReceiver);
      }
   }
}

function ApplyGravity ()
{   var Stat = GetComponent(Stat);
   var J2 = Stat.jump;
   // Apply gravity
   var jumpButton = Input.GetButton ("Jump");
   
   if (!canControl)
      jumpButton = false;
   
   // When we reach the apex of the jump we send out a message
   if (jump.jumping && !jump.reachedApex && movement.verticalSpeed <= 0.0) {
      jump.reachedApex = true;
      SendMessage ("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);
   }
   
   // * When jumping up we don't apply gravity for some time when the user is holding the jump button
   //   This gives more control over jump height by pressing the button longer
   var extraPowerJump =  jump.jumping && movement.verticalSpeed > 0.0 && jumpButton && transform.position.y < jump.lastStartHeight + J2 && !IsTouchingCeiling ();
   
   if (extraPowerJump)
      return;
   else if (controller.isGrounded)
      movement.verticalSpeed = -movement.gravity * Time.deltaTime;
   else
      movement.verticalSpeed -= movement.gravity * Time.deltaTime;
      
   // Make sure we don't fall any faster than maxFallSpeed.  This gives our character a terminal velocity.
   movement.verticalSpeed = Mathf.Max (movement.verticalSpeed, -movement.maxFallSpeed);
}

function CalculateJumpVerticalSpeed (targetJumpHeight : float) {
   // From the jump height and gravity we deduce the upwards speed
   // for the character to reach at the apex.
   return Mathf.Sqrt (2 * targetJumpHeight * movement.gravity);
}

function DidJump () {
   jump.jumping = true;
   jump.reachedApex = false;
   jump.lastTime = Time.time;
   jump.lastStartHeight = transform.position.y;
   jump.lastButtonTime = -10;
}

function Update ()
   {
   //if (Input.GetButtonUp("Horizontal"))
   
//transform.rotation.y = myCamera.rotation.y;


      if (Input.GetButtonDown ("Jump") && canControl)
      {
         jump.lastButtonTime = Time.time;
      }

   UpdateSmoothedMovementDirection();
   
   // Apply gravity
   // - extra power jump modifies gravity
   ApplyGravity ();

   // Apply jumping logic
   ApplyJumping ();
   
   // Moving platform support
   if (activePlatform != null) {
      var newGlobalPlatformPoint = activePlatform.TransformPoint(activeLocalPlatformPoint);
      var moveDistance = (newGlobalPlatformPoint - activeGlobalPlatformPoint);
      transform.position = transform.position + moveDistance;
      lastPlatformVelocity = (newGlobalPlatformPoint - activeGlobalPlatformPoint) / Time.deltaTime;
   } else {
      lastPlatformVelocity = Vector3.zero;   
   }
   
   activePlatform = null;
   
   // Save lastPosition for velocity calculation.
   lastPosition = transform.position;
   
   // Calculate actual motion
   var currentMovementOffset = movement.direction * movement.speed + Vector3 (0, movement.verticalSpeed, 0) + movement.inAirVelocity;
   
   // We always want the movement to be framerate independent.  Multiplying by Time.deltaTime does this.
   currentMovementOffset *= Time.deltaTime;
   
      // Move our character!
   movement.collisionFlags = controller.Move (currentMovementOffset);
   
   // Calculate the velocity based on the current and previous position. 
   // This means our velocity will only be the amount the character actually moved as a result of collisions.
   //movement.velocity = (transform.position - lastPosition) / Time.deltaTime;
   
   // Moving platforms support
   if (activePlatform != null) {
      activeGlobalPlatformPoint = transform.position;
      activeLocalPlatformPoint = activePlatform.InverseTransformPoint (transform.position);
   }
   

   // We are in jump mode but just became grounded
   if (controller.isGrounded) {
      movement.inAirVelocity = Vector3.zero;
      if (jump.jumping) {
         jump.jumping = false;
         SendMessage ("DidLand", SendMessageOptions.DontRequireReceiver);

         var jumpMoveDirection = movement.direction * movement.speed + movement.inAirVelocity;
         if (jumpMoveDirection.sqrMagnitude > 0.01)
            movement.direction = jumpMoveDirection.normalized;
      }
   }   
}

function OnControllerColliderHit (hit : ControllerColliderHit)
{
   if (hit.moveDirection.y > 0.01)
      return;
   
   // Make sure we are really standing on a straight platform
   // Not on the underside of one and not falling down from it either!
   if (hit.moveDirection.y < -0.9 && hit.normal.y > 0.9) {
      activePlatform = hit.collider.transform;   
   }
}

// Various helper functions below:
function GetSpeed () {
   return movement.speed;
}

function GetVelocity () {
   return movement.velocity;
}


function IsMoving () {
   return movement.isMoving;
}

function IsMoving2 () {
   return movement.isMoving2;
}


function IsJumping () {
   return jump.jumping;
}

function IsTouchingCeiling () {
   return (movement.collisionFlags & CollisionFlags.CollidedAbove) != 0;
}

function GetDirection () {
   return movement.direction;
}

function GetHangTime() {
   return movement.hangTime;
}

function Reset () {
   gameObject.tag = "Player";
}

function SetControllable (controllable : boolean) {
   canControl = controllable;
}

function USE (U1 : float)
{
   Using = U1;
}



// Require a character controller to be attached to the same game object
@script RequireComponent (CharacterController)
@script AddComponentMenu ("2D Platformer/Platformer Controller")


На счет - "Все мои трансформы работают именно на кинетическом приращении дельты к текущей позиции" - а можно чутку подробнее?
Аватара пользователя
Garu
UNITрон
 
Сообщения: 199
Зарегистрирован: 13 авг 2009, 18:26

Re: (Проблема) движение на движущемся объекте

Сообщение Paul Siberdt 15 авг 2010, 11:27

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

Re: (Проблема) движение на движущемся объекте

Сообщение Garu 16 авг 2010, 07:06

в общем единственный способ, который "хавается" ступеньками и всем кораблем нормально, это объект без управления, с ригидбоди (гравитация без разницы - обе ест), но обязательно что бы объект был чайлдом корабля, если объект из обычной сцены - при начале движения корабля, остается на своем месте, только чуть вертится (из-за задевания кораблем) и все, полностью игнорит параметр is kinematic на ригидбоде кораблика, но делать так, что бы персонаж при условии Х закидывался в чайлд корабля, мне кажется это не самое вкусное решение... Но пока другого не придумалось.
Аватара пользователя
Garu
UNITрон
 
Сообщения: 199
Зарегистрирован: 13 авг 2009, 18:26

Re: (Проблема) движение на движущемся объекте

Сообщение warr11r 16 авг 2010, 21:16

Физику чаще обновляйте. Таймстеп раза в 2 меньше сделайте.
Мудрость - это когда начинаешь понимать, что все время занимаешься какой-то х...ней.
Изображение
Аватара пользователя
warr11r
UNITрон
 
Сообщения: 310
Зарегистрирован: 06 июн 2009, 03:21
Откуда: Украина, Ровно
  • ICQ

Re: (Проблема) движение на движущемся объекте

Сообщение Garu 17 авг 2010, 14:20

По сути все тоже, любые шаманства оканчиваются тем, что - предмет с коллайдером + ригидбоди в чаелде корабля дает сносный результат, тоже самое не являясь чаелдом корабля дает 0 эффекта. Про персонажа естественно даже молчу, при таких результатах. Да и очень уж не горю желанием, решать все через перекидывание объектов в чайлд корабля и обратно, топорно это как-то.
Аватара пользователя
Garu
UNITрон
 
Сообщения: 199
Зарегистрирован: 13 авг 2009, 18:26

Re: (Проблема) движение на движущемся объекте

Сообщение warr11r 17 авг 2010, 19:44

Насколько я знаю, это делается одной командой. Но, к сожалению, может повлечь за собой другие глюки
Мудрость - это когда начинаешь понимать, что все время занимаешься какой-то х...ней.
Изображение
Аватара пользователя
warr11r
UNITрон
 
Сообщения: 310
Зарегистрирован: 06 июн 2009, 03:21
Откуда: Украина, Ровно
  • ICQ

След.

Вернуться в Скрипты

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

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