Предварительный расчёт физики для отдельной модели

Физика в Unity

Предварительный расчёт физики для отдельной модели

Сообщение xkor 23 ноя 2010, 20:21

Доброго времени суток, продумываю написание сетевого гоночного симулятора на unity и для синхронизации положения автомобилей игроков надо бы в некоторые моменты рассчитывать где будет автомобиль через несколько десятых долей секунды. Собственно вопрос в том можно ли это реализовать на unity и если да то где бы можно было хоть что то почитать на эту тему ибо в гугле ничего адекватного не нашел, хотя я и не совсем представляю как обозвать то что ищу.
xkor
UNец
 
Сообщения: 16
Зарегистрирован: 23 ноя 2010, 20:07
Откуда: Питер
  • Сайт
  • ICQ

Re: Предварительный расчёт физики для отдельной модели

Сообщение Ert Donuell 23 ноя 2010, 20:47

Попробовать не заморачиваться и использовать для своих целей Badumna Network Suite - он за Вас всё синхронизирует)
Добавить dmitrii.baranov.yumasoft в Skype
Аватара пользователя
Ert Donuell
Старожил
 
Сообщения: 781
Зарегистрирован: 05 июл 2010, 09:50
Откуда: Санкт-Петербург
  • ICQ

Re: Предварительный расчёт физики для отдельной модели

Сообщение xkor 23 ноя 2010, 21:50

И как же он интересно компенсирует запаздывание информации о положении на сумму пингов игроков до сервера? В гонках запаздывание на 50 миллисекунд приведет к смещению машины от реального положения на несколько метров! А 50 мсек это ещё очень хороший пинг...
xkor
UNец
 
Сообщения: 16
Зарегистрирован: 23 ноя 2010, 20:07
Откуда: Питер
  • Сайт
  • ICQ

Re: Предварительный расчёт физики для отдельной модели

Сообщение Palmer 21 мар 2011, 20:24

можно отправлять не только положение машины но и скорость, как во всех нормальных играх.
Аватара пользователя
Palmer
UNец
 
Сообщения: 35
Зарегистрирован: 27 фев 2011, 01:44
  • Сайт

Re: Предварительный расчёт физики для отдельной модели

Сообщение xkor 21 мар 2011, 21:50

спасибо капитан очевидность...
xkor
UNец
 
Сообщения: 16
Зарегистрирован: 23 ноя 2010, 20:07
Откуда: Питер
  • Сайт
  • ICQ

Re: Предварительный расчёт физики для отдельной модели

Сообщение pod4444 27 мар 2012, 12:11

вам просто нужна интерполяция и экстраполяция. сорри, что уже некрофильно, но авось кому пригодится.
Синтаксис:
Используется csharp
public class NetworkRigidbody : MonoBehaviour {
       
        private double m_InterpolationBackTime = 0.1;
        private double m_ExtrapolationLimit = 0.5;
       
        internal struct  State
        {
                internal double timestamp;
                internal Vector3 pos;
                internal Vector3 velocity;
                internal Quaternion rot;
                internal Vector3 angularVelocity;
        }
       
        // We store twenty states with "playback" information
        State[] m_BufferedState = new State[40];
        // Keep track of what slots are used
        int m_TimestampCount;
       
       
       
        void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)
        {
       
                // Send data to server
                if (stream.isWriting)
                {
                        Vector3 pos = transform.position;
                        Quaternion rot = transform.rotation;
                        Vector3 velocity = Vector3.zero;  //rigidbody.velocity;
                        Vector3 angularVelocity = Vector3.zero; // rigidbody.angularVelocity;

                        stream.Serialize(ref pos);
                        stream.Serialize(ref velocity);
                        stream.Serialize(ref rot);
                        stream.Serialize(ref angularVelocity);
                }
                // Read data from remote client
                else
                {
                        Vector3 pos = Vector3.zero;
                        Vector3 velocity = Vector3.zero;
                        Quaternion rot = Quaternion.identity;
                        Vector3 angularVelocity = Vector3.zero;
                        stream.Serialize(ref pos);
                        stream.Serialize(ref velocity);
                        stream.Serialize(ref rot);
                        stream.Serialize(ref angularVelocity);
                       
                        // Shift the buffer sideways, deleting state 20
                        for (int i=m_BufferedState.Length-1;i>=1;i--)
                        {
                                m_BufferedState[i] = m_BufferedState[i-1];
                        }
                       
                        // Record current state in slot 0
                        State state;
                        state.timestamp = info.timestamp;
                        state.pos = pos;
                        state.velocity = velocity;
                        state.rot = rot;
                        state.angularVelocity = angularVelocity;
                        m_BufferedState[0] = state;
                       
                        // Update used slot count, however never exceed the buffer size
                        // Slots aren't actually freed so this just makes sure the buffer is
                        // filled up and that uninitalized slots aren't used.
                        m_TimestampCount = Mathf.Min(m_TimestampCount + 1, m_BufferedState.Length);

                        // Check if states are in order, if it is inconsistent you could reshuffel or
                        // drop the out-of-order state. Nothing is done here
                        for (int i=0;i<m_TimestampCount-1;i++)
                        {
                                if (m_BufferedState[i].timestamp < m_BufferedState[i+1].timestamp)
                                        Debug.Log("State inconsistent");
                        }      
                }
        }
       
        // We have a window of interpolationBackTime where we basically play
        // By having interpolationBackTime the average ping, you will usually use interpolation.
        // And only if no more data arrives we will use extra polation
        void Update () {
                if(!networkView.isMine)
                {
                // This is the target playback time of the rigid body
                double interpolationTime = Network.time - m_InterpolationBackTime;
               
                // Use interpolation if the target playback time is present in the buffer
                if (m_BufferedState[0].timestamp > interpolationTime)
                {
                        // Go through buffer and find correct state to play back
                        for (int i=0;i<m_TimestampCount;i++)
                        {
                                if (m_BufferedState[i].timestamp <= interpolationTime || i == m_TimestampCount-1)
                                {
                                        // The state one slot newer (<100ms) than the best playback state
                                        State rhs = m_BufferedState[Mathf.Max(i-1, 0)];
                                        // The best playback state (closest to 100 ms old (default time))
                                        State lhs = m_BufferedState[i];
                                       
                                        // Use the time between the two slots to determine if interpolation is necessary
                                        double length = rhs.timestamp - lhs.timestamp;
                                        float t = 0.0F;
                                        // As the time difference gets closer to 100 ms t gets closer to 1 in
                                        // which case rhs is only used
                                        // Example:
                                        // Time is 10.000, so sampleTime is 9.900
                                        // lhs.time is 9.910 rhs.time is 9.980 length is 0.070
                                        // t is 9.900 - 9.910 / 0.070 = 0.14. So it uses 14% of rhs, 86% of lhs
                                        if (length > 0.0001){
                                                t = (float)((interpolationTime - lhs.timestamp) / length);
                                        }
                                        //      Debug.Log(t);
                                        // if t=0 => lhs is used directly
                                        transform.position = Vector3.Lerp(lhs.pos, rhs.pos, t);
                                        transform.rotation = Quaternion.Slerp(lhs.rot, rhs.rot, t);
                                        return;
                                }
                        }
                }
                // Use extrapolation
                else
                {
                        State latest = m_BufferedState[0];
                       
                        float extrapolationLength = (float)(interpolationTime - latest.timestamp);
                        // Don't extrapolation for more than 500 ms, you would need to do that carefully
                        if (extrapolationLength < m_ExtrapolationLimit)
                        {
                                float axisLength = extrapolationLength * latest.angularVelocity.magnitude * Mathf.Rad2Deg;
                                Quaternion angularRotation = Quaternion.AngleAxis(axisLength, latest.angularVelocity);
                               
                                transform.position = latest.pos + latest.velocity * extrapolationLength;
                                transform.rotation = angularRotation * latest.rot;
                                rigidbody.velocity = latest.velocity;
                                rigidbody.angularVelocity = latest.angularVelocity;
                        }
                }
                }
        }
        void Awake()
        {
                if(!networkView.isMine)
                {
                State latest = m_BufferedState[0];
                transform.position = latest.pos;
                transform.rotation = latest.rot;
                rigidbody.velocity = latest.velocity;
                rigidbody.angularVelocity = latest.angularVelocity;
                }
        }
}
 
Аватара пользователя
pod4444
Старожил
 
Сообщения: 721
Зарегистрирован: 20 янв 2012, 22:02
Откуда: Воронеж
Skype: pod4444
  • Сайт

Re: Предварительный расчёт физики для отдельной модели

Сообщение xkor 27 мар 2012, 12:40

Спасибо, но интерполяция и экстраполяция позволят рассчитать правильное положение лишь при условии что объект не войдёт во взаимодействие с другими движущимися объектами, а я хотел реализовать возможность толкаться и что бы динамические препятствия были.
В общем я пришел к выводу что для достижения моих целей надо физику рассчитывать на стороне сервера, а на стороне клиента физику использовать лишь для просчёта положений объектов в интервале между получением от сервера информации о новом состоянии мира. Это заодно минимизирует возможность читерить. Правда при этом отзывчивость управления будет не на высоте, но думаю вполне приемлемо. Примерно так например в WorldOfTanks сделано, но там скорости не особо гоночные.
ЗЫ на игру я правда уже подзабил в виду нехватки времени, она так и осталась на стадии экспериментов с физикой.
xkor
UNец
 
Сообщения: 16
Зарегистрирован: 23 ноя 2010, 20:07
Откуда: Питер
  • Сайт
  • ICQ


Вернуться в PhysX

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

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