Esempio n. 1
0
        protected void ReturnNode(Pool <ProjectileData> .Node node)
        {
            if (node.Active)
            {
                node.Item.TimeToLive = -1;
                if (node.Item.Outline.Item != null)
                {
                    ProjectileOutlines.Return(node.Item.Outline.NodeIndex);
                    node.Item.Outline.Item = null;
                }

                Projectiles.Return(node.NodeIndex);
                node.Active = false;
            }
        }
Esempio n. 2
0
        private void UpdateProjectiles(float tick)
        {
            ActiveProjectileCount = 0;

            ContactFilter2D contactFilter = new ContactFilter2D
            {
                layerMask   = LayerMask,
                useTriggers = true,
            };

            ProjectileManager projectileManager = ProjectileManager.Instance;

            //Update camera planes if needed
            if (CullProjectilesOutsideCameraBounds)
            {
                GeometryUtility.CalculateFrustumPlanes(Camera, Planes);
            }

            // loop through all active projectile data
            for (int i = 0; i < Projectiles.Nodes.Length; i++)
            {
                if (Projectiles.Nodes[i].Active)
                {
                    Projectiles.Nodes[i].Item.TimeToLive -= tick;

                    // Projectile is active
                    if (Projectiles.Nodes[i].Item.TimeToLive > 0)
                    {
                        // apply acceleration
                        Projectiles.Nodes[i].Item.Velocity *= (1 + Projectiles.Nodes[i].Item.Acceleration * tick);

                        // apply gravity
                        Projectiles.Nodes[i].Item.Velocity += Projectiles.Nodes[i].Item.Gravity * tick;

                        // calculate where projectile will be at the end of this frame
                        Vector2 deltaPosition = Projectiles.Nodes[i].Item.Velocity * tick;
                        float   distance      = deltaPosition.magnitude;

                        // If flag set - return projectiles that are no longer in view
                        if (CullProjectilesOutsideCameraBounds)
                        {
                            Bounds bounds = new Bounds(Projectiles.Nodes[i].Item.Position, new Vector3(Projectiles.Nodes[i].Item.Scale, Projectiles.Nodes[i].Item.Scale, Projectiles.Nodes[i].Item.Scale));
                            if (!GeometryUtility.TestPlanesAABB(Planes, bounds))
                            {
                                Projectiles.Nodes[i].Item.TimeToLive = -1;
                                Projectiles.Return(Projectiles.Nodes[i].NodeIndex);
                            }
                        }

                        int result = -1;
                        if (CollisionDetection == CollisionDetectionType.Raycast)
                        {
                            result = Physics2D.Raycast(Projectiles.Nodes[i].Item.Position, deltaPosition, contactFilter, RaycastHitBuffer, distance);
                        }
                        else if (CollisionDetection == CollisionDetectionType.CircleCast)
                        {
                            result = Physics2D.CircleCast(Projectiles.Nodes[i].Item.Position, Projectiles.Nodes[i].Item.Scale / 2f, Projectiles.Nodes[i].Item.Velocity, contactFilter, RaycastHitBuffer, distance);
                            if (result > 0 && RaycastHitBuffer[0].distance == 0)
                            {
                                result = -1;
                            }
                        }


                        if (result > 0)
                        {
                            if (RaycastHitBuffer.Length == 1)
                            {
                                if (RaycastHitBuffer[0].collider.gameObject.tag == "NotForBullet" ||
                                    RaycastHitBuffer[0].collider.gameObject.tag == shooterTag)
                                {
                                    result = -1;
                                }
                            }
                        }

                        if (result > 0)
                        {
                            // Put whatever hit code you want here such as damage events
                            if (RaycastHitBuffer.Length > 1)
                            {
                                Debug.LogWarning("[彈幕系統]超過一個Raycast目標!");
                            }

                            if (RaycastHitBuffer[0].collider.GetComponent <LivingObject>())
                            {
                                RaycastHitBuffer[0].collider.GetComponent <LivingObject>().GetHurt(atk);
                            }


                            // Collision was detected, should we bounce off or destroy the projectile?
                            if (BounceOffSurfaces)
                            {
                                // rudementary bounce -- will work well on static surfaces
                                Projectiles.Nodes[i].Item.Velocity = Vector2.Reflect(Projectiles.Nodes[i].Item.Velocity, RaycastHitBuffer[0].normal);

                                // what fraction of the distance do we still have to move this frame?
                                float leakedFraction = 1f - RaycastHitBuffer[0].distance / distance;

                                deltaPosition = Projectiles.Nodes[i].Item.Velocity * tick * leakedFraction;
                                Projectiles.Nodes[i].Item.Position = RaycastHitBuffer[0].centroid + deltaPosition;
                                Projectiles.Nodes[i].Item.Color    = Color.Evaluate(1 - Projectiles.Nodes[i].Item.TimeToLive / TimeToLive);

                                // Absorbs energy from bounce
                                Projectiles.Nodes[i].Item.Velocity = new Vector2(Mathf.Lerp(Projectiles.Nodes[i].Item.Velocity.x, 0, BounceAbsorbtion.x), Mathf.Lerp(Projectiles.Nodes[i].Item.Velocity.y, 0, BounceAbsorbtion.y));

                                projectileManager.UpdateBufferData(ActiveProjectileCount, ProjectileType, Projectiles.Nodes[i].Item);

                                ActiveProjectileCount++;
                            }
                            else
                            {
                                Projectiles.Nodes[i].Item.TimeToLive = -1;
                                Projectiles.Return(Projectiles.Nodes[i].NodeIndex);
                            }
                        }
                        else
                        {
                            //No collision -move projectile
                            Projectiles.Nodes[i].Item.Position += deltaPosition;
                            Projectiles.Nodes[i].Item.Color     = Color.Evaluate(1 - Projectiles.Nodes[i].Item.TimeToLive / TimeToLive);

                            projectileManager.UpdateBufferData(ActiveProjectileCount, ProjectileType, Projectiles.Nodes[i].Item);

                            ActiveProjectileCount++;
                        }
                    }
                    else
                    {
                        // End of life - return to pool
                        Projectiles.Return(Projectiles.Nodes[i].NodeIndex);
                    }
                }
            }
        }