Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
  • Need help?

    Create a topic in the appropriate section
    Don't write everything in the chat!
  • Take a look at the marketplace

    There you can buy
    everything related to game servers
  • Don't want a ban?

    Please read our rules
    Don't disturb the order!
  • Sell or buy?

    Use services of the guarantor
    We will make your deal safe
  • 0
Akuma

Анимация самолёта

Привет, может кто знает как решить проблему с самиком
Вкратце, у меня есть скрипт, который спавнит самолёт в небе(модельку взял обычного разрушеного с130), он летит по указаным координатам и падает там скользя по земле, но есть проблема, которая меня сильно вымораживает, это то, как он перемещается, как будто фпс 20 у него, даже поставив минимальное значение обновления тика
Не обращайте внимания на его подскоки в небе и на то, что нос поднимается в земле


 

class Plane_Base
{
	protected EntityAI m_Plane;

	protected ref Timer m_MoveTimer;
	protected float     m_LastUpdateTime;

	protected vector m_StartPos;
	protected vector m_EndPos;
	protected vector m_TargetPos;
	protected vector m_DirNorm;
	protected vector m_ForwardDir;
	protected float  m_PathLenXZ;
	protected float  m_PathDoneXZ;

	protected float  m_UpdateInterval;
	protected float  m_DiveStartDist; 
	protected float  m_SpeedMS;
	protected float  m_AltitudeAGL;     
	protected float  m_RotationLerp;

	protected vector m_CurrentOrientation;

	
	protected bool   m_DiveMode;        
	protected bool   m_SlideMode;       
	protected bool   m_NoseRaiseArmed; 

	
	protected float  m_SlideSpeed;
	protected float  m_SlideFriction;
	protected float  m_SlideHeight;     
	protected float  m_SlideTrigger;    
	protected float  m_StopRadius;      

	
	protected float  m_PitchDownDeg;
	protected float  m_PitchRateDegPerSec; 
	protected float  m_TargetPitch;     

	
	protected string m_WreckClass;
	protected float  m_WreckYOffset;

	
	protected float  m_YawOffsetDeg;
	protected float  m_LastGoodYawDeg;

	void Plane_Base(PlaneEventManager mgr = null)
	{
		m_MoveTimer       = null;
		m_LastUpdateTime  = 0;

		m_PathLenXZ       = 0;
		m_PathDoneXZ      = 0;

		m_UpdateInterval  = 0.01;
		m_SpeedMS         = 55.0;
		m_DiveStartDist   = 900.0;
		m_AltitudeAGL     = 230.0;  
		m_RotationLerp    = 0.1;

		m_DiveMode        = false;
		m_NoseRaiseArmed  = false; 

		m_SlideMode       = false;
		m_SlideSpeed      = 0.0;
		m_SlideFriction   = 14.0;
		m_SlideHeight     = 5.0;   
		m_SlideTrigger    = 120.0;  
		m_StopRadius      = 0.5;

		m_PitchDownDeg       = 15.0;  
		m_PitchRateDegPerSec = 40.0;  
		m_TargetPitch        = 0.0;

		m_WreckClass      = "Crash_Wreck_C130J";
		m_WreckYOffset    = 0.20;

		m_YawOffsetDeg    = 180.0;   
		m_LastGoodYawDeg  = 0.0;
	}

	protected float ClampF(float v, float a, float b)
	{
		if (v < a) return a;
		if (v > b) return b;
		return v;
	}

	protected float YawFromDir(vector d)
	{
		return Math.Atan2(d[0], d[2]) * Math.RAD2DEG;
	}

	void SpawnAndFly(vector startPos, vector endPos, float speedMS = 60.0, float altitudeAGL = 200.0, string planeClass = "Crash_Wreck_C130J", string wreckClass = "Crash_Wreck_C130J")
	{
		m_DiveMode      = false;
		m_SlideMode     = false;
		m_NoseRaiseArmed = false;
		m_TargetPitch   = 0.0;

		m_WreckClass    = wreckClass;
		StartCommon(startPos, endPos, speedMS, altitudeAGL, planeClass);
	}

	void SpawnAndDive(vector startPos, vector targetPos, float speedMS = 60.0, float startAltitudeAGL = 200.0, float endAltitudeAGL = 0.30, float unused = 0.0, string planeClass = "Crash_Wreck_C130J", string wreckClass = "Crash_Wreck_C130J")
	{
		m_DiveMode      = true;
		m_SlideMode     = false;
		m_NoseRaiseArmed = false;
		m_TargetPitch   = 0.0;

		m_SlideHeight   = endAltitudeAGL; 
		m_WreckClass    = wreckClass;

		StartCommon(startPos, targetPos, speedMS, startAltitudeAGL, planeClass);
	}

	protected void StartCommon(vector startPos, vector endPos, float speedMS, float altitudeAGL, string planeClass)
	{
		if (!GetGame().IsServer()) return;

		m_SpeedMS      = speedMS;
		m_AltitudeAGL  = altitudeAGL;
		m_StartPos     = startPos;
		m_EndPos       = endPos;
		m_TargetPos    = endPos;

		vector diffXZ = endPos - startPos; diffXZ[1] = 0;
		float distanceXZ = Math.Sqrt(diffXZ[0]*diffXZ[0] + diffXZ[2]*diffXZ[2]);
		if (distanceXZ < 0.1) distanceXZ = 0.1;

		float invLen = 1.0 / distanceXZ;
		m_DirNorm     = diffXZ * invLen;
		m_ForwardDir  = m_DirNorm;
		m_PathLenXZ   = distanceXZ;
		m_PathDoneXZ  = 0.0;

		
		vector pos = startPos;
		float ground = GetGame().SurfaceY(pos[0], pos[2]);
		pos[1] = ground + m_AltitudeAGL;

		m_Plane = EntityAI.Cast(GetGame().CreateObject(planeClass, pos, false, true, true));
		if (!m_Plane) return;

		float yawStart = YawFromDir(m_ForwardDir) + m_YawOffsetDeg;
		m_LastGoodYawDeg = yawStart;

		
		m_CurrentOrientation = Vector(yawStart, m_PitchDownDeg, 0);
		m_Plane.SetOrientation(m_CurrentOrientation);

		if (!m_MoveTimer) m_MoveTimer = new Timer(CALL_CATEGORY_GAMEPLAY);
		m_LastUpdateTime = GetGame().GetTime();
		m_MoveTimer.Run(m_UpdateInterval, this, "TickMove", null, true);
	}

	protected void TickMove()
	{
		if (!GetGame().IsServer()) return;
		if (!m_Plane) { StopAndDelete(); return; }

		float tNow = GetGame().GetTime();
		float dt   = (tNow - m_LastUpdateTime) / 1000.0;
		if (dt <= 0) { dt = m_UpdateInterval; }
		m_LastUpdateTime = tNow;

		vector pos = m_Plane.GetPosition();

		if (!m_SlideMode)
		{
			vector stepXZ = m_DirNorm * (m_SpeedMS * dt);
			pos[0] = pos[0] + stepXZ[0];
			pos[2] = pos[2] + stepXZ[2];

			
			float remX = m_TargetPos[0] - pos[0];
			float remZ = m_TargetPos[2] - pos[2];
			float rem  = Math.Sqrt(remX*remX + remZ*remZ);

			
			float ground    = GetGame().SurfaceY(pos[0], pos[2]);
			float flightY   = ground + m_AltitudeAGL;   
			float slideY    = ground + m_SlideHeight;   м
			float tBlend    = 1.0;

			if (m_DiveStartDist < m_SlideTrigger + 1.0)
			{
				m_DiveStartDist = m_SlideTrigger + 50.0; 
			}
			if (rem <= m_DiveStartDist)
			{
				float denom = (m_DiveStartDist - m_SlideTrigger);
				if (denom < 1.0) { denom = 1.0; }
				tBlend = (rem - m_SlideTrigger) / denom; 
				if (tBlend < 0.0) tBlend = 0.0;
				if (tBlend > 1.0) tBlend = 1.0;
			}

			
			pos[1] = slideY + (flightY - slideY) * tBlend;

			m_Plane.SetPosition(pos);

			if (!m_NoseRaiseArmed && rem <= m_SlideTrigger)
        	{
            	m_NoseRaiseArmed = true;
        	}

			
			UpdateOrientation(stepXZ, dt);

			
			float stepLenXZ = Math.Sqrt(stepXZ[0]*stepXZ[0] + stepXZ[2]*stepXZ[2]);
			m_PathDoneXZ = m_PathDoneXZ + stepLenXZ;

			
			if (rem <= m_SlideTrigger || m_PathDoneXZ >= m_PathLenXZ)
			{
				
				float gyG = GetGame().SurfaceY(pos[0], pos[2]);
				pos[1] = gyG + m_SlideHeight;
				m_Plane.SetPosition(pos);

				
				m_SlideMode  = true;
				m_SlideSpeed = m_SpeedMS;

				
				vector toSlide = m_TargetPos - pos; toSlide[1] = 0;
				float d2 = toSlide[0]*toSlide[0] + toSlide[2]*toSlide[2];
				if (d2 < 0.0001) { d2 = 0.0001; }
				float inv = 1.0 / Math.Sqrt(d2);
				m_ForwardDir = toSlide * inv;

				float yawNow = YawFromDir(m_ForwardDir) + m_YawOffsetDeg;
				m_LastGoodYawDeg = yawNow;

				
			}
		}
		else
		{
			
			vector toT = m_TargetPos - pos; toT[1] = 0;
			float dist = Math.Sqrt(toT[0]*toT[0] + toT[2]*toT[2]);

			
			if (dist <= m_StopRadius || m_SlideSpeed <= 0.1)
			{
				float gyEnd = GetGame().SurfaceY(pos[0], pos[2]);
				pos[1] = gyEnd + m_SlideHeight;
				m_Plane.SetPosition(pos);

				
				vector finalDir = m_TargetPos - m_StartPos; finalDir[1] = 0;
				if (finalDir[0]*finalDir[0] + finalDir[2]*finalDir[2] > 0.0001)
				{
					float yawFin = YawFromDir(finalDir) + m_YawOffsetDeg;
					m_LastGoodYawDeg = yawFin;
					m_CurrentOrientation = Vector(yawFin, 0, 0);
					m_Plane.SetOrientation(m_CurrentOrientation);
				}

				SpawnWreckAndDelete(pos);
				return;
			}

			
			float invd = 1.0 / Math.Max(0.0001, dist);
			vector dirTo = toT * invd;

			float moveLen = m_SlideSpeed * dt;
			if (moveLen > dist) { moveLen = dist; }
			vector step = dirTo * moveLen;

			pos[0] = pos[0] + step[0];
			pos[2] = pos[2] + step[2];

			
			float gy = GetGame().SurfaceY(pos[0], pos[2]);
			pos[1] = gy + m_SlideHeight;

			m_Plane.SetPosition(pos);

			
			float yawDeg = YawFromDir(dirTo) + m_YawOffsetDeg;
			m_LastGoodYawDeg = yawDeg;
			m_CurrentOrientation = Vector(yawDeg, m_CurrentOrientation[1], 0);
			m_Plane.SetOrientation(m_CurrentOrientation);

			
			m_SlideSpeed = m_SlideSpeed - (m_SlideFriction * dt);
			if (m_SlideSpeed < 0.0) { m_SlideSpeed = 0.0; }

			
			UpdateOrientation(dirTo * m_SlideSpeed, dt);
		}
	}



	protected void UpdateOrientation(vector stepXZ, float dt)
	{
		float yaw   = m_CurrentOrientation[0];
		float pitch = m_CurrentOrientation[1];
		float roll  = m_CurrentOrientation[2];

	
		float yawDeg = YawFromDir(m_DirNorm) + m_YawOffsetDeg;
		yaw = yawDeg;
		m_LastGoodYawDeg = yawDeg;

		float desiredRaw;
		if (m_SlideMode)
		{
			desiredRaw = 0.0;
		}
		else
		{
			if (m_NoseRaiseArmed)
			{
				desiredRaw = 0.0;
			}
			else
			{
				desiredRaw = m_PitchDownDeg; 
			}
		}

		
		float diff    = desiredRaw - m_TargetPitch;
		float maxStep = m_PitchRateDegPerSec * dt;
		if (diff >  maxStep)
		{
			diff =  maxStep;
		}
		if (diff < -maxStep)
		{
			diff = -maxStep;
		}
		m_TargetPitch = m_TargetPitch + diff;

		
		float k = m_RotationLerp * dt * 25.0;
		if (k > 0.5)
		{
			k = 0.5;
		}
		pitch = Math.Lerp(pitch, m_TargetPitch, k);

		
		roll  = Math.Lerp(roll, 0.0, k);

		m_CurrentOrientation = Vector(yaw, pitch, roll);
		m_Plane.SetOrientation(m_CurrentOrientation);
	}



	protected void SpawnWreckAndDelete(vector atPos)
	{
		float gx = atPos[0];
    	float gz = atPos[2];

    	float gyTerrain = GetGame().SurfaceY(gx, gz);
		vector wreckPos = Vector(gx, gyTerrain + 5.0, gz);

		EntityAI wreck = EntityAI.Cast(GetGame().CreateObject(m_WreckClass, wreckPos, false, true, true));
		if (wreck)
		{
			vector o = Vector(m_LastGoodYawDeg, 0, 0);
			wreck.SetOrientation(o);
		}

		StopAndDelete();
	}

	void StopAndDelete()
	{
		if (m_MoveTimer) m_MoveTimer.Stop();
		if (m_Plane)
		{
			GetGame().ObjectDelete(m_Plane);
			m_Plane = null;
		}
	}
}


 

 

Edited by Akuma (see edit history)

Share this post


Link to post
Share on other sites

1 answer to this question

Recommended Posts

  • 0

Проблема заключается в том, что ты вызываешь установку позиций с серверной части. Грамотным решением реализации будет отправка rpc на клиент, уведомляя клиента о том, что самолёт вылетел, а далее спавнить локальный самолёт и менять ему уже позицию на клиентской части.

Edited by Stein35 (see edit history)

Share this post


Link to post
Share on other sites
MagicByte MagicByte MagicByte

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site, you automaticly agree to our Guidelines and Privacy Policy.
We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.

Поддержка