Ejemplo n.º 1
0
    public virtual void Tick(float deltaTime)
    {
        physicsTransform.Mass = projectileData.bulletMass;
        //affectors.ForEach(n => n.Tick_PrePhysics(deltaTime));

        foreach (AffectorBase affector in affectors)
        {
            affector.Tick_PrePhysics(deltaTime);
        }

        physicsTransform.Tick(deltaTime);

        //If we hit something, process it
        TerminalBallisticsData terminalData = terminalDetector.Tick(this);        //, true); //Have we hit anything?

        if (terminalData != null)
        {
            terminalCalculators.ForEach(n => n.ProcessTerminalHit(terminalData)); //We have hit something!
        }
        if (IsDead())                                                             //Do this speed check before an effector speeds us up again
        {
            Active = false;                                                       //Only set this when we actually die
        }
        //affectors.ForEach(n => n.Tick_PostPhysics(deltaTime));

        foreach (AffectorBase affector in affectors)
        {
            affector.Tick_PostPhysics(deltaTime);
        }

        //Debug information
        //Debug.DrawLine(physicsTransform.PrevPosition, physicsTransform.Position, Color.blue, 120);
        //DrawingFuncs.DrawStar(physicsTransform.Position, Color.green, 0.5f, 120);
        physicsTransform.RenderDebug(deltaTime, deltaTime, 20.0f);
    }
Ejemplo n.º 2
0
    //Split this up into multiple calculators
    public virtual void ProcessTerminalHit(TerminalBallisticsData penData)
    {
        //penData.projectile.physicsTransform.Position = penData.hitInfo.point;

        #region Projectile Hitable

        //If object is IProjectileHitable, then 'hit' it

        IProjectileHitable hitable = penData.hitInfo.collider.GetComponent <IProjectileHitable>();

        if (hitable != null)
        {
            hitable.Hit(penData.projectile, penData.hitInfo);

            //{TODO} Properly setup how much kinetic energy we lose to the impact
            if (hitable.recieveImpulse)
            {
                penData.hitInfo.collider.attachedRigidbody.AddForceAtPosition(
                    penData.projectile.physicsTransform.Velocity,
                    penData.projectile.physicsTransform.Position,
                    ForceMode.Impulse
                    );
            }
        }


        #endregion
    }
Ejemplo n.º 3
0
    /// <summary>
    ///
    /// </summary>
    /// <param name="penData"></param>
    /// <returns>bool willPenetrate, float penetrationDepth</returns>
    protected virtual Tuple <bool, float> WillPen(TerminalBallisticsData penData)
    {
        ProjectileData          projData         = penData.projectile.projectileData;
        VirtualPhysicsTransform physicsTransform = penData.projectile.physicsTransform;

        //(assuming 0 degrees is hitting straight on)
        //If angleWeHitTarget >= 80 degrees, then richochet
        if (Vector3.Angle(physicsTransform.Velocity.normalized, -penData.hitInfo.normal) >= 80)
        {
            return(new Tuple <bool, float>(false, 0.0f));           //When Unity supports C#7, switch this to the new syntax
        }
        //Otherwise, do some more testing

        float targetDensity = 1000.0f;         //{TODO} Hook this up

        //tex:
        //$$stoppingDist=\sqrt[3]{\frac{projMass * initVel^2}{targetDensity*projCrossArea * projDragCoefficient}} $$
        //Heavily simplified model

        float stoppingDist =
            Mathf.Pow(                                                                                                                    //3rd root
                (projData.bulletMass * physicsTransform.VelocityMagnitude * physicsTransform.VelocityMagnitude)                           //{TODO} Make velocity relative to target
                /
                (targetDensity * projData.CrossSectionalArea * projData.GetDragCoefficient(physicsTransform.Velocity.magnitude / 343.0f)) //{TODO} Rewrite correctly!
                , (1.0f / 3.0f)
                );

        return(new Tuple <bool, float>(stoppingDist >= projData.noseLength, stoppingDist));
    }
Ejemplo n.º 4
0
    public override void ProcessTerminalHit(TerminalBallisticsData penData)
    {
        //penData.projectile.physicsTransform.Position = penData.hitInfo.point + (penData.hitInfo.normal * 0.01f);
        //penData.projectile.physicsTransform.Position = penData.projectile.physicsTransform.PrevPosition;

        base.ProcessTerminalHit(penData);

        Tuple <bool, float> willPenInfo = WillPen(penData);


        if (willPenInfo.Item1)
        {
            Penetrate(penData, willPenInfo.Item2);
        }
        else
        {
            Richochet(penData);
        }
    }
Ejemplo n.º 5
0
    protected virtual void Richochet(TerminalBallisticsData penData)
    {
        //Move us back so we don't morph through the ground
        penData.projectile.physicsTransform.Position = penData.hitInfo.point + (penData.hitInfo.normal * 0.01f);
        //{TODO} Tie this up together with how much energy we lose to the rigidbody
        //Restitution dependant richochet
        PhysicMaterial physMat =
            penData.hitInfo.collider.gameObject.GetComponent <BoxCollider>().material;

        penData.projectile.physicsTransform.Velocity =
            (physMat == null)
                        ? //If the hit object does not have a physics material, then just do a normal reflect
            Vector3.Reflect(penData.projectile.physicsTransform.Velocity, penData.hitInfo.normal)
                        : //However, if the object does have a physics material, lerp from a reflect and simply stopping
                          //{TODO} Make this more realistic
            Vector3.Lerp(
                Vector3.zero,
                Vector3.Reflect(penData.projectile.physicsTransform.Velocity, penData.hitInfo.normal),
                physMat.bounciness *
                Vector3.Cross(penData.projectile.physicsTransform.Velocity.normalized, penData.hitInfo.normal).magnitude         //Bounce more if we hit the surface at a sharp angle
                );
    }
Ejemplo n.º 6
0
    //{TODO} Damn this method is long...
    protected virtual void Penetrate(TerminalBallisticsData penData, float stoppingDist)
    {
        ProjectileData          projData         = penData.projectile.projectileData;
        VirtualPhysicsTransform physicsTransform = penData.projectile.physicsTransform;
        float targetDensity = 1000.0f;         //{TODO} Hook this up

        //343.0f - Temporary hardcoded value - 1 mach in air ~= 343 m/s

        ThicknessData objectThickness =
            ProjectileHelper.FindThickness(
                physicsTransform.PrevPosition,
                physicsTransform.Velocity.normalized,
                (rCH) => rCH.collider.gameObject == penData.hitInfo.collider.gameObject);         //Only colliders on this object


        Debug.Log($"Thickness: {objectThickness.thickness}m");

        //{TODO} Add some check to see if the object thickness was even found

        //If the projectile stops mid-object, de-activate it
        if (stoppingDist <= objectThickness.thickness)
        {
            penData.projectile.Active = false;
            Debug.Log($"Stopped after penetrating {stoppingDist}m");
            return;
        }

        //Otherwise, see how fast we come out the other side
        physicsTransform.Position = objectThickness.exitPosition;

        //tex:
        //$$ v=\sqrt{-\frac{ACpx^3}{m}+u^2}$$

        physicsTransform.VelocityMagnitude =
            Mathf.Sqrt(
                -
                (
                    (
                        projData.CrossSectionalArea *
                        projData.GetDragCoefficient(physicsTransform.Velocity.magnitude / 343.0f) *
                        targetDensity *
                        objectThickness.thickness * objectThickness.thickness * objectThickness.thickness
                    )
                    /
                    projData.bulletMass
                )
                + (physicsTransform.VelocityMagnitude * physicsTransform.VelocityMagnitude)
                );

        //Modify the exit direction depending on the projectile velocity
        //{TODO} Rewrite!
        float range = 0.25f;

        physicsTransform.VelocityDirection +=
            Vector3.Lerp(
                new Vector3(
                    CryptoRand.Range(-range, range),
                    CryptoRand.Range(-range, range),
                    CryptoRand.Range(-range, range)),
                Vector3.zero,
                Mathf.Clamp(1 / physicsTransform.VelocityMagnitude, 0, 1)
                );

        Debug.Log($"Stopping distance: {stoppingDist}");
        Debug.Log($"Fully penetrated with an exit velocity of {physicsTransform.Velocity.magnitude}m/s");
    }