Ejemplo n.º 1
0
        /// <summary>
        /// calculate bullet flights
        /// </summary>
        void UpdateBullets()
        {
            float deltaTime = Time.deltaTime;


            float leftOverFlyTime = 0;
            float myDeltaTime     = 0;
            bool  processAgain    = true;

#if (UNITY_EDITOR && BULLET_DEBUGGER)
            BulletDebugger debugger = null;
#endif

            //Process each Bullet
            for (int i = 0; i < Bullets.Count; i++)
            {
                if (i < MaxBulletUpdatesPerFrame)
                {
                    BulletData cBullet = Bullets[0];
                    Bullets.RemoveAt(0);

                    Weapon cWeapon = cBullet.parentWeapon;

#if (UNITY_EDITOR && BULLET_DEBUGGER)
                    if (cBullet.BulletTrans != null)
                    {
                        debugger = cBullet.BulletTrans.GetComponent <BulletDebugger>();
                    }
                    else
                    {
                        debugger = null;
                    }
#endif

                    processAgain = true;
                    while (processAgain)
                    {
                        //when current bullet passed processing already but has 'flytime over'
                        if (leftOverFlyTime == 0)
                        {
                            myDeltaTime = deltaTime;
                        }
                        else
                        {
                            myDeltaTime     = leftOverFlyTime;
                            leftOverFlyTime = 0;
                        }

                        //when this bullet had to wait in the query for more than 1 frame
                        if (cBullet.timeSinceLastUpdate > 0)
                        {
                            myDeltaTime += cBullet.timeSinceLastUpdate;
                            cBullet.timeSinceLastUpdate = 0;
                        }

                        //decrease Lifetime
                        cBullet.lifeTime -= myDeltaTime;
                        if (cBullet.lifeTime <= 0)
                        {
                            //remove Bullet if dead
                            DeactivateBullet(cWeapon, cBullet.BulletTrans);
                            processAgain = false;
                            continue;
                        }


                        //Move Bullet
#if (UNITY_EDITOR && BULLET_DEBUGGER)
                        if (debugger != null)
                        {
                            debugger.AddPos(cBullet.bulletPos);
                        }
#endif

                        cBullet.bulletPos += cBullet.bulletDir * cBullet.Speed * myDeltaTime;

                        //if (Settings.useBulletdrop)
                        //{
                        //Bulletdrop
                        //cBullet.ySpeed += g * myDeltaTime;

                        //if (Settings.useBulletdrag)
                        //{
                        //cBullet.ySpeed += cWeapon.PreDrag * ((cBullet.ySpeed * cBullet.ySpeed)) * myDeltaTime;
                        //}

                        //cBullet.bulletPos.y += cBullet.ySpeed * myDeltaTime;
                        //}

                        //Hitcheck------------------
                        Vector3 realBulletDir = cBullet.bulletPos - cBullet.LastPos;
                        float   dirMag        = realBulletDir.magnitude;
                        //bullet speed + fall speed
                        float      rBulletSpeed = dirMag / myDeltaTime;
                        Ray        ray          = new Ray(cBullet.LastPos, realBulletDir);
                        RaycastHit hit;

                        if (Physics.Raycast(ray, out hit, dirMag, cWeapon.HitMask))
                        {
                            Transform       hitTrans = hit.transform;
                            BallisticObject hitBallisticObject;

                            hitBallisticObject = Settings.useBallisticMaterials ? hitTrans.GetComponent <BallisticObject>() : null;

                            if ((hitBallisticObject != null) ? hitBallisticObject.MatID >= Settings.MaterialData.Count : true)
                            {
                                //hit object has no ballistic material
#if (UNITY_EDITOR && BULLET_DEBUGGER)
                                if (debugger != null)
                                {
                                    debugger.AddPos(hit.point);
                                }
#endif

                                //Stop Bullet
                                DeactivateBullet(cWeapon, cBullet.BulletTrans);
                                processAgain = false;
                                continue;
                            }
                            else
                            {
                                BallisticObjectData hitData = Settings.MaterialData[hitBallisticObject.MatID];

                                Vector3 bulletDirNormalized = realBulletDir.normalized;

                                //does this bullet ricochet?
                                if (hitData.RicochetPropability.Evaluate(Vector3.Angle(hit.normal, -bulletDirNormalized) / 90f) < Random.Range(0f, 1f))
                                {
                                    //maximal material penetration distance of this bullet
                                    float MaxRange = (0.5f * cWeapon.BulletMass * rBulletSpeed * rBulletSpeed) / hitData.EnergylossPerUnit;

                                    //backtrace the bulletpath to find out whether the bullet went through the material
                                    ray = new Ray(hit.point + bulletDirNormalized * MaxRange, -bulletDirNormalized);
                                    RaycastHit[] hits = Physics.RaycastAll(ray, MaxRange, cWeapon.HitMask);


                                    int   OutIndex     = -1;
                                    float shortestDist = 0f;
                                    for (int n = 0; n < hits.Length; n++)
                                    {
                                        if (hits[n].transform == hitTrans)
                                        {
                                            //backwards
                                            if (hits[n].distance > shortestDist)
                                            {
                                                OutIndex     = n;
                                                shortestDist = hits[n].distance;
                                            }
                                        }
                                    }

                                    if (OutIndex != -1)
                                    {
                                        //Shoot through
                                        RaycastHit outHit = hits[OutIndex];

                                        //slowdown
                                        float dist       = (outHit.point - hit.point).magnitude;
                                        float fac        = 1 - (dist / MaxRange);
                                        float afterSpeed = rBulletSpeed * (1 - fac);
                                        cBullet.ySpeed *= fac;
                                        cBullet.Speed  *= fac;

                                        //Spread
                                        cBullet.bulletDir = hitData.RndSpread > 0 ? (Quaternion.AngleAxis(Random.Range(0f, 360f), cBullet.bulletDir) * Quaternion.AngleAxis(Random.Range(0f, hitData.RndSpread), Vector3.Cross(Vector3.up, cBullet.bulletDir)) * cBullet.bulletDir) : cBullet.bulletDir;


                                        //process Bullet again
                                        leftOverFlyTime = ((cBullet.bulletPos - outHit.point).magnitude / dirMag) * myDeltaTime;

                                        //call BulletImpact on the hitBallisticObject
                                        hitBallisticObject.BulletImpact(cWeapon, bulletDirNormalized, rBulletSpeed, afterSpeed, dist, hit, hitData);

                                        //bullet exit
                                        hitBallisticObject.BulletImpact(cWeapon, bulletDirNormalized, afterSpeed, afterSpeed, dist, outHit, hitData);

                                        cBullet.bulletPos = cBullet.LastPos = outHit.point;

#if (UNITY_EDITOR && BULLET_DEBUGGER)
                                        if (debugger != null)
                                        {
                                            debugger.AddPos(cBullet.bulletPos);
                                        }
#endif

                                        processAgain = true;
                                        continue;
                                    }
                                    else
                                    {
                                        //Bullet stuck in object


                                        //call BulletImpact on the hitBallisticObject
                                        hitBallisticObject.BulletImpact(cWeapon, bulletDirNormalized, rBulletSpeed, 0, MaxRange, hit, hitData);

#if (UNITY_EDITOR && BULLET_DEBUGGER)
                                        if (debugger != null)
                                        {
                                            debugger.AddPos(hit.point);
                                        }
#endif

                                        //Stop Bullet
                                        DeactivateBullet(cWeapon, cBullet.BulletTrans);
                                        processAgain = false;
                                        continue;
                                    }
                                }
                                else
                                {
                                    //Ricochet

                                    //Reflect bullet
                                    cBullet.bulletDir = Vector3.Reflect(bulletDirNormalized, hit.normal);

                                    cBullet.bulletDir = hitData.RndSpreadRic > 0 ? (Quaternion.AngleAxis(Random.Range(0f, 360f), cBullet.bulletDir) * Quaternion.AngleAxis(Random.Range(0f, hitData.RndSpreadRic), Vector3.Cross(hit.normal, cBullet.bulletDir)) * cBullet.bulletDir) : cBullet.bulletDir;

                                    //Slowdown
                                    float fac = 1f - (Vector3.Angle(bulletDirNormalized, cBullet.bulletDir) / 180f);
                                    cBullet.Speed  = cBullet.Speed * fac;
                                    cBullet.ySpeed = 0;

                                    leftOverFlyTime = ((hit.point - cBullet.bulletPos).magnitude / (myDeltaTime * rBulletSpeed)) * myDeltaTime;

                                    //call BulletImpact on the hitBallisticObject
                                    hitBallisticObject.BulletImpact(cWeapon, -hit.normal, rBulletSpeed, rBulletSpeed * fac, 0.1f, hit, hitData);

                                    //process Bullet again
                                    cBullet.bulletPos = cBullet.LastPos = hit.point;

#if (UNITY_EDITOR && BULLET_DEBUGGER)
                                    if (debugger != null)
                                    {
                                        debugger.AddPos(cBullet.bulletPos);
                                    }
#endif

                                    processAgain = true;
                                    continue;
                                }
                            }
                        }
                        processAgain = false;

                        cBullet.LastPos = cBullet.bulletPos;
                        //Update Transform
                        if (cBullet.BulletTrans != null)
                        {
                            if (cBullet.StartLifeTime - cBullet.lifeTime < VisualBulletToRealBulletMovementTime)
                            {
                                cBullet.VisualOffset = Vector3.Lerp(cBullet.StartOffset, Vector3.zero, (cBullet.StartLifeTime - cBullet.lifeTime) / VisualBulletToRealBulletMovementTime);
                            }
                            else
                            {
                                cBullet.VisualOffset = Vector3.zero;
                            }
                            cBullet.BulletTrans.position = cBullet.bulletPos + cBullet.VisualOffset;

                            cBullet.BulletTrans.rotation = Quaternion.LookRotation(realBulletDir);
                        }
                        //Enqueue at End
                        Bullets.Add(cBullet);
                    }
                }
                else
                {
                    BulletData cBullet = Bullets[i];
                    cBullet.timeSinceLastUpdate += Time.deltaTime;
                }
            }
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Add Bullet to update list
 /// </summary>
 /// <param name="bullet">new Bullet Data</param>
 public void AddBullet(BulletData bullet)
 {
     Bullets.Add(bullet);
 }