Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using UnityEngine;
- using Cooper.Core;
- using Cooper.Maths;
- namespace Assets.World.Entities.Scripts
- {
- /// <summary>
- /// Entity Interpolation.
- /// Le but de ce code est d'interpoler la position d'une entitée entre un point a (xyz) et b (xyz).
- /// Pour pouvoir interpoler entre un point a et un point b, on est forcé de connaître b, c'est pourquoi on affiche l'entité dans le
- /// passé. (décalé de 1 message de déplacement).
- /// entre xyz(t) et xyz(t+1). xyz correspond a la position de l'entitée et t le temps auquel ce message de position a été reçu.
- /// Dans ce cas présent, nous n'utilisons donc pas le TickRate d'un serveur.
- /// Voici le calcul du ratio utilisé par Vector3.Lerp() = temps écoulé depuis le temps de départ / (temps arrivée - temps départ)
- /// on simplifira l'expression par te / (ta - td)
- /// La difficultée réside dans le calcul de te , car il s'agit d'une variable dépendant du temps, borné entre ta et td.
- /// L'expression de te, (calculer dans FixedUpdate) est : (ta - td) / POSITION_UPDATE_FRAMES_COUNT
- /// POSITION_UPDATE_FRAMES_COUNT = fréquence d'envoit de la position par le client.
- /// Une autre difficulté est la prise en compte du ping dans les calcul, qui est suceptible de varier et donc d'amener a
- /// une interpolation non linéaire.
- /// Il faut traiter le cas particulier ou :
- /// Previous Position n'existe pas. (ou la définir autrement= basePosition)
- /// Il faut traiter le cas particulier ou :
- /// On reçoit une nouvelle position alors que le GameObject n'est pas encore arrivé a la destination imposée par Entity.NextPosition.Position.
- /// Il faut : Repenser l'architecture de cette interpolation et savoir si les propriétées NextPosition & PreviousPosition
- /// sont englobés dans ce script, ou dans Player. En auront nous besoin plus tard, ne pouvons nous pas nous contenter d'utiliser ce
- /// script.
- /// </summary>
- public class EntityInterpolationScript : UnityEntityScript<Player>
- {
- /// <summary>
- /// Le pourcentage de temps entre td et ta
- /// </summary>
- private float CurrentRatio
- {
- get
- {
- return (float)(CurrentTime / TotalTime);
- }
- }
- /// <summary>
- /// Le temps total qu'a mit l'entitée a se déplacer entre a et b
- /// </summary>
- private float TotalTime
- {
- get
- {
- return (float)(NextPosition.Time - PreviousPosition.Time).TotalMilliseconds;
- }
- }
- /// <summary>
- /// Le temps actuel
- /// </summary>
- private double CurrentTime
- {
- get;
- set;
- }
- /// <summary>
- /// La position de départ de l'entitée.
- /// </summary>
- public EntityPositionExtended PreviousPosition
- {
- get;
- private set;
- }
- /// <summary>
- /// La position d'arrivée de l'entitée
- /// </summary>
- public EntityPositionExtended NextPosition
- {
- get;
- private set;
- }
- /// <summary>
- /// Doit t-on interpoler?
- /// Seulement si la position d'arrivée envoyée par le serveur est différente de la position actuelle de l'objet.
- /// </summary>
- public bool InterpolationRequired
- {
- get
- {
- return NextPosition.Position.HasValue && (NextPosition.Position.Value != gameObject.transform.position || NextPosition.Rotation.Value != gameObject.transform.eulerAngles.y);
- }
- }
- public void FixedUpdate()
- {
- if (InterpolationRequired)
- {
- CurrentTime += (TotalTime / MainPlayerScript.PositionUpdateFrameCount.Value);
- }
- }
- public void Update()
- {
- if (InterpolationRequired)
- {
- var result = Vector3.Lerp(PreviousPosition.Position.Value, NextPosition.Position.Value, CurrentRatio);
- if (float.IsNaN(result.x))
- {
- return;
- }
- transform.position = result;
- Quaternion a = Geometry.ModifyQuaternion(transform.rotation, PreviousPosition.Rotation.Value);
- Quaternion b = Geometry.ModifyQuaternion(transform.rotation, NextPosition.Rotation.Value);
- transform.rotation = Quaternion.Slerp(a, b, CurrentRatio);
- }
- }
- /// <summary>
- /// Fonction appellée lorsque le client reçoit la nouvelle position de cette entitée.
- /// </summary>
- /// <param name="position">nouvelle position de l'entitée</param>
- public void OnPositionReceived(Vector3 position, float rotation)
- {
- if (NextPosition.Position == null) // tout première position reçue. (Previous est donc indéfinie)
- {
- NextPosition = new EntityPositionExtended(position, rotation, DateTime.Now);
- }
- this.gameObject.transform.position = NextPosition.Position.Value; // Quoi qu'il arrive avec l'interpolation, l'entitée est téléportée au point d'arrivée
- this.gameObject.transform.rotation = Geometry.ModifyQuaternion(transform.rotation, NextPosition.Rotation.Value);
- CurrentTime = 0; // Le compteur de temps repart a 0
- PreviousPosition = NextPosition; // La position précédente devient l'ancienne.
- NextPosition = new EntityPositionExtended(position, rotation, DateTime.Now);
- }
- }
- /// <summary>
- /// Structure représentant une position reçue par le client
- /// </summary>
- public struct EntityPositionExtended
- {
- /// <summary>
- /// Position de l'entitée
- /// </summary>
- public Vector3? Position;
- /// <summary>
- /// Date a laquelle cette position a été reçue.
- /// </summary>
- ///
- public float? Rotation;
- public DateTime Time;
- public EntityPositionExtended(Vector3 position, float rotation, DateTime time)
- {
- this.Position = position;
- this.Time = time;
- this.Rotation = rotation;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement