示例#1
0
    //##############################################################################################
    // If the colliding object is the player, find matching ammo types and give the gun ammo.
    // If marked to, destroy this object on pickup
    //##############################################################################################
    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Player")
        {
            GunComponent[] playerGuns = other.gameObject.GetComponents <GunComponent>();

            bool gaveAmmo = false;

            foreach (var gun in playerGuns)
            {
                // Only pickup if the gun isn't maxed out already
                if (gun.currentGunData.ammoType == ammoType && gun.GetRemainingBoxAmmoCount() < gun.currentGunData.maxBoxAmmoCount)
                {
                    gaveAmmo = true;
                    gun.GiveAmmo(ammoType, pickupAmount);

                    if (!giveAmmoToAllGuns)
                    {
                        break;
                    }
                }
            }

            if (gaveAmmo)
            {
                SoundManagerComponent.PlaySound(ammoPickupSound, gameObject);

                if (destroyOnPickup)
                {
                    Destroy(gameObject);
                }
            }
        }
    }
 //##############################################################################################
 // If marked to, stop the sound on disable
 //##############################################################################################
 void OnDisable()
 {
     if (stopOnDisable && id != SoundManagerComponent.INVALID_SOUND)
     {
         SoundManagerComponent.StopSound(id);
     }
 }
 //##############################################################################################
 // If marked to, stop the sound on destroy
 //##############################################################################################
 void OnDestroy()
 {
     if (stopOnDestroy && id != SoundManagerComponent.INVALID_SOUND)
     {
         SoundManagerComponent.StopSound(id);
     }
 }
    //##############################################################################################
    // Do a simple random selection of the next bark. If it's the same one, decrement to get a
    // different one. Only do this if we have enough barks. Then play the sound, and record the
    // result.
    //##############################################################################################
    public void Bark()
    {
        if (barks.Length < 1)
        {
            return;
        }

        int newPickedBark = previousPickedBark;

        if (barks.Length != 1)
        {
            newPickedBark = Random.Range(0, barks.Length);

            if (newPickedBark == previousPickedBark)
            {
                newPickedBark = (newPickedBark + 1) % barks.Length;
            }
        }
        else
        {
            newPickedBark = 0;
        }

        SoundManagerComponent.PlaySound(barks[newPickedBark], gameObject);
        previousPickedBark = newPickedBark;
    }
 //##############################################################################################
 // Play the sound with the given settings, on this gameObject, and cache the resulting id
 //##############################################################################################
 public void Play()
 {
     id = SoundManagerComponent.PlaySound(
         sound,
         gameObject
         );
 }
示例#6
0
    //##############################################################################################
    // Used to reload the gun, whether manually in a subclass, or from running out of bullets
    //##############################################################################################
    protected void ReloadGun()
    {
        reloading = true;
        reloadTimer.Start();

        // Play reloading sound if it exists
        if (currentGunData.reloadSound != null)
        {
            reloadSoundId = SoundManagerComponent.PlaySound(currentGunData.reloadSound, muzzleTransform.gameObject);
        }
    }
    //##############################################################################################
    // If the colliding object is the player, heal them for the specified amount
    // If marked to, and only if the heal occured, destroy this object on pickup
    //##############################################################################################
    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Player")
        {
            if (other.GetComponent <DamageableComponent>().Heal(healAmount))
            {
                SoundManagerComponent.PlaySound(healthPickupSound, gameObject);

                if (destroyOnPickup)
                {
                    Destroy(gameObject);
                }
            }
        }
    }
示例#8
0
    //##############################################################################################
    // When triggered, kick off playing the new sound (at very small volume) and kick off the fading
    //
    // This system uses TwoDimensional sound, because it's meant to feel omnipresent and ambient
    // without any particular directionality.
    //##############################################################################################
    private void OnTriggerEnter(Collider other)
    {
        // Ignore disabled components
        if (!enabled)
        {
            return;
        }

        if (other.tag == "Player")
        {
            fading = true;
            fadeTimer.Start();

            fadingInSoundId = SoundManagerComponent.PlaySound(sound, gameObject);
        }
    }
示例#9
0
    //##############################################################################################
    // Get the player input and trigger the shooting, then play out the appropriate animation
    // based on the state of the gun.
    //##############################################################################################
    protected new void Update()
    {
        base.Update();

        // Don't update animated gun if the player is dead
        if (damage.Dead())
        {
            return;
        }

        // Either use getMouseButton if the gun is automatic, or getMouseButtonDown if not
        bool inputTriggerPulled = currentGunData.automaticAction ? Input.GetMouseButton(0) : Input.GetMouseButtonDown(0);

        if (inputTriggerPulled)
        {
            // If we are a manual reload and it's a progressive, interruptible load, do the interrupt
            if (reloading && currentGunData.manualReload && currentGunData.progressiveReloadInterruption)
            {
                reloading = false;

                // If playing a reload sound, try to stop it.
                if (reloadSoundId != SoundManagerComponent.INVALID_SOUND)
                {
                    SoundManagerComponent.StopSound(reloadSoundId);
                }
            }

            if (base.Shoot())
            {
                player.AddGunRecoil(this);
            }
        }

        bool reloadInput = Input.GetKeyDown(KeyCode.R); // TODO make this a setting

        if (!reloading && reloadInput && currentGunData.useAmmo && currentGunData.manualReload && remainingMagazineAmmoCount < currentGunData.maxMagazineAmmoCount && remainingBoxAmmoCount != 0)
        {
            ReloadGun();
        }

        bool zooming = Zooming();

        gunAnimator.SetBool(idleAnimationName, !shooting && !reloading && !zooming);
        gunAnimator.SetBool(shootAnimationName, shooting && !zooming);
        gunAnimator.SetBool(reloadAnimationName, reloading && !zooming);
        gunAnimator.SetBool(scopeAnimationName, zooming);
    }
示例#10
0
    //##############################################################################################
    // If it's fading, drive the fade from the timer. Fade out the old sound and in the new.
    // When finished, stop the old, then set the shared current sound.
    //##############################################################################################
    void Update()
    {
        if (fading)
        {
            float p = fadeTimer.Parameterized();

            if (currentAmbientSoundId != SoundManagerComponent.INVALID_SOUND)
            {
                SoundManagerComponent.SetSoundVolume(currentAmbientSoundId, (1.0f - p));
            }

            if (fadingInSoundId != SoundManagerComponent.INVALID_SOUND)
            {
                SoundManagerComponent.SetSoundVolume(fadingInSoundId, p);
            }

            if (fadeTimer.Finished())
            {
                fading = false;
                SoundManagerComponent.StopSound(currentAmbientSoundId);
                currentAmbientSoundId = fadingInSoundId;
            }
        }
    }
示例#11
0
    //##############################################################################################
    // Update the bullet, moving it along it's velocity, unless it collides with something.
    // If that something is a damageable, deal the damage to it. Either way, mark the bullet
    // for destruction next update.
    // This is done in Fixed Update so that the physics is properly synchronized for the bullet.
    //##############################################################################################
    void FixedUpdate()
    {
        // Prevents updating before firing information has been provided, since fixed update is
        // disjoint from regular unity update
        if (!fired)
        {
            return;
        }

        // The destruction is done 1 frame after being marked for kill so the bullet and effects
        // appear in the correct position visually for that last frame, before bullet is destroyed.
        if (shouldKill)
        {
            // Notify all delegates
            if (bulletDestroyedDelegates != null)
            {
                foreach (OnBulletDestroyed bulletDestroyedDelegate in bulletDestroyedDelegates)
                {
                    bulletDestroyedDelegate();
                }
            }

            // Destroy if not pooled, otherwise mark this bullet as freed
            if (poolIdentifier == null)
            {
                Destroy(gameObject);
            }
            else
            {
                PooledGameObjectManager.FreeInstanceToPool(poolIdentifier, gameObject);
            }

            return;
        }

        velocity += Physics.gravity * gravityModifier * Time.deltaTime * Time.deltaTime;
        Vector3 move     = velocity * Time.deltaTime;
        float   moveDist = move.magnitude;

        // Kill the bullet if it's gone too far
        if ((transform.position - startPosition).sqrMagnitude >= maxDistance * maxDistance)
        {
            shouldKill = true;
        }

        // See if move would hit anything, ignoring the 'no bullet collide' layer and triggers
        RaycastHit hit;

        if (Physics.Raycast(transform.position, move, out hit, moveDist, ~NO_BULLET_COLLIDE_LAYER, QueryTriggerInteraction.Ignore))
        {
            if (hit.collider.gameObject != firer)
            {
                transform.position = hit.point;

                DamageableComponent damageable = hit.collider.gameObject.GetComponent <DamageableComponent>();

                if (damageable == null)
                {
                    DamageablePieceComponent damageablePiece = hit.collider.gameObject.GetComponent <DamageablePieceComponent>();

                    if (damageablePiece != null)
                    {
                        damageable = damageablePiece.GetDamageableComponent();
                    }
                }

                if (damageable != null)
                {
                    // Never ricochet off a damageable
                    collisionsRemaining = 0;
                    damageable.DealDamage(damage, type, startPosition, firer);
                }
                else
                {
                    // Don't spawn decals when hitting damageable
                    if (optionalDecalObject != null && damageable == null)
                    {
                        GameObject decalInstance = GameObject.Instantiate(optionalDecalObject);

                        // Add random offset to prevent z-fighting
                        float randomOffset = (Random.value * BULLET_EFFECTS_OFFSET);

                        decalInstance.transform.position = hit.point + (hit.normal * (BULLET_DECAL_OFFSET + randomOffset));
                        decalInstance.transform.rotation = Quaternion.LookRotation(hit.normal);
                    }

                    // TODO add impact effects lookup system for hit object
                    if (optionalImpactEffects != null)
                    {
                        GameObject fx = GameObject.Instantiate(optionalImpactEffects);

                        // Scoot fx back away from collision a little
                        fx.transform.position = transform.position + (-move).normalized * BULLET_EFFECTS_OFFSET;
                    }
                }

                // Play impact sound if needed
                if (impactSound != null)
                {
                    SoundManagerComponent.PlaySound(impactSound, gameObject);
                }

                if (collisionsRemaining > 0)
                {
                    collisionsRemaining--;

                    if (Random.value <= collisionModeChance)
                    {
                        if (collisionMode == CollisionMode.Ricochet)
                        {
                            float velocityMagnitude = velocity.magnitude;
                            velocity           = Vector3.Reflect(velocity.normalized, hit.normal).normalized *velocityMagnitude;
                            transform.position = hit.point + (velocity * 0.01f);
                        }
                        else if (collisionMode == CollisionMode.Pierce)
                        {
                            transform.position += move;
                        }
                    }
                    else
                    {
                        collisionsRemaining = 0;
                    }
                }

                if (collisionsRemaining <= 0)
                {
                    shouldKill = true;
                }
            }
        }
        else
        {
            transform.position += move;
        }
    }
    //##############################################################################################
    // Get the player input and trigger the shooting, then play out the appropriate animation
    // based on the state of the gun.
    //##############################################################################################
    protected new void Update()
    {
        base.Update();

        if (tintWithNearestLight)
        {
            UpdateTintWithNearestLight();
        }

        // Don't update the rest of the animated gun if the player is dead
        if (damage.Dead())
        {
            return;
        }

        if (useGunBob)
        {
            UpdateGunBob();
        }

        // Either use getMouseButton if the gun is automatic, or getMouseButtonDown if not
        bool inputTriggerPulled = currentGunData.automaticAction ? Input.GetMouseButton(0) : Input.GetMouseButtonDown(0);

        if (inputTriggerPulled)
        {
            // If we are a manual reload and it's a progressive, interruptible load, do the interrupt
            if (reloading && currentGunData.manualReload && currentGunData.progressiveReloadInterruption)
            {
                reloading = false;

                // If playing a reload sound, try to stop it.
                if (reloadSoundId != SoundManagerComponent.INVALID_SOUND)
                {
                    SoundManagerComponent.StopSound(reloadSoundId);
                }
            }

            if (base.Shoot())
            {
                currentFrame = 0;

                player.AddGunRecoil(this);

                if (reloading)
                {
                    reloadingAnimationTimer.Start();
                    state = AnimatedGunState.Reloading;
                    gunSpriteImage.sprite = reloadingSprites[0];
                }
                else
                {
                    firingAnimationTimer.Start();
                    state = AnimatedGunState.Shooting;
                    gunSpriteImage.sprite = firingSprites[0];
                }
            }
        }

        bool reloadInput = Input.GetKeyDown(KeyCode.R); // TODO make this a setting

        if (!reloading && reloadInput && currentGunData.useAmmo && currentGunData.manualReload && remainingMagazineAmmoCount < currentGunData.maxMagazineAmmoCount && remainingBoxAmmoCount != 0)
        {
            ReloadGun();

            reloadingAnimationTimer.Start();
            state = AnimatedGunState.Reloading;
            gunSpriteImage.sprite = reloadingSprites[0];
            currentFrame          = 0;
        }

        // Animating the Gun
        if (state == AnimatedGunState.Shooting)
        {
            if (firingAnimationTimer.Finished())
            {
                firingAnimationTimer.Start();

                currentFrame++;

                if (currentFrame >= firingSprites.Length)
                {
                    state = AnimatedGunState.Idle;
                    gunSpriteImage.sprite = idleSprite;
                }
                else
                {
                    gunSpriteImage.sprite = firingSprites[currentFrame];
                }
            }
        }
        else if (state == AnimatedGunState.Reloading)
        {
            if (reloadingAnimationTimer.Finished())
            {
                reloadingAnimationTimer.Start();

                currentFrame++;

                if (currentFrame >= reloadingSprites.Length || !reloading)
                {
                    state = AnimatedGunState.Idle;
                    gunSpriteImage.sprite = idleSprite;
                }
                else
                {
                    gunSpriteImage.sprite = reloadingSprites[currentFrame];
                }
            }
        }
    }
    //##############################################################################################
    // Setup the instance, sources, records, and raycast directions.
    // Also error check the whole process.
    //##############################################################################################
    public void Awake()
    {
        instance = this;

        // Setup records, hinting at the capacity
        if (records == null)
        {
            soundIdIndex = 0;

            records          = new List <SoundRecord>();
            records.Capacity = SOUND_SOURCE_COUNT;
        }

        // Setup the sources from scratch, creating a new gameObject and adding the needed components
        // Then, place these newly created sources into the unusedSources
        if (usedSources == null)
        {
            usedSources          = new List <AudioSource>();
            usedSources.Capacity = SOUND_SOURCE_COUNT;

            transform.position = Vector3.zero;

            unusedSources = new Queue <AudioSource>();

            for (int i = 0; i < SOUND_SOURCE_COUNT; ++i)
            {
                GameObject newObject = new GameObject();
                newObject.AddComponent <AudioSource>();

                newObject.AddComponent <AudioReverbFilter>();
                newObject.GetComponent <AudioReverbFilter>().reverbPreset = AudioReverbPreset.Off;

                newObject.AddComponent <AudioLowPassFilter>();
                newObject.GetComponent <AudioLowPassFilter>().cutoffFrequency = SoundConstants.LPF_CLEAR;

                newObject.gameObject.transform.parent = transform;

                #if UNITY_EDITOR
                newObject.gameObject.name = ("Sound " + i);
                #endif // UNITY_EDITOR

                AudioSource source = newObject.GetComponent <AudioSource>();
                unusedSources.Enqueue(source);
            }
        }

        // Basically just hard-code the 6 cardinal directions into the array, so we can loop over
        // them later, when calculating reverb for each direction.
        if (raycastDirections == null)
        {
            raycastDirections = new Vector3[DIRECTIONS_COUNT];

            raycastDirections[0] = Vector3.up;
            raycastDirections[1] = -Vector3.up;
            raycastDirections[2] = Vector3.right;
            raycastDirections[3] = -Vector3.right;
            raycastDirections[4] = Vector3.forward;
            raycastDirections[5] = -Vector3.forward;
        }

        // Check that the audio listener in game is set up correctly. This is necessary, so the
        // occlusion raycasts don't collide against the listener itself.
        AudioListener audioListener = FindObjectOfType(typeof(AudioListener)) as AudioListener;
        listener = audioListener.gameObject;

        if (1 << listener.layer != IGNORE_SOUND_RAYCAST_LAYER)
        {
            Logger.Error("Listener " + listener + " has incorrect layer " + (1 << listener.layer) + ", should be " + IGNORE_SOUND_RAYCAST_LAYER);
        }
    }
示例#14
0
    //##############################################################################################
    // Create the bullet(s) and send them shooting in the direction of muzzleTransform. Also spawn
    // effects if available.
    // The argument can be used to change the damage amount (usually called from subclasses to
    // modify damage)
    // return value indicates whether or not the gun actually fired.
    //##############################################################################################
    public bool Shoot(float damage)
    {
        if (gunTimer.Finished() && !reloading)
        {
            if (remainingMagazineAmmoCount == 0 && remainingBoxAmmoCount == 0)
            {
                return(BULLET_NOT_FIRED);
            }

            gunTimer.Start();
            shooting = true;

            remainingMagazineAmmoCount--;
            if (remainingMagazineAmmoCount == 0 && remainingBoxAmmoCount > 0)
            {
                ReloadGun();
            }

            // This is for shotgun-type weapons. It spawns several bullets in a random cone
            for (int i = 0; i < currentGunData.shots; ++i)
            {
                GameObject bulletInstance = null;

                if (currentGunData.usePooledBullets)
                {
                    bulletInstance = PooledGameObjectManager.GetInstanceFromPool(currentGunData.poolIdentifier);
                }
                else
                {
                    bulletInstance = GameObject.Instantiate(currentGunData.bulletPrefab);
                }

                BulletComponent bullet = bulletInstance.GetComponent <BulletComponent>();

                if (currentGunData.usePooledBullets)
                {
                    bullet.SetAsPooled(currentGunData.poolIdentifier);
                }

                if (bullet == null)
                {
                    Logger.Error("Bullet Prefab " + currentGunData.bulletPrefab.name + " must have a bullet component");
                    return(BULLET_NOT_FIRED);
                }

                // Apply non-zero spread. This can be for shotgun scatter,
                // or for inaccurate, normal guns
                Quaternion spreadOffset = Quaternion.identity;
                if (currentGunData.spread > 0.0f)
                {
                    spreadOffset = Quaternion.AngleAxis(Random.value * currentGunData.spread, Vector3.right);
                    Quaternion rot = Quaternion.AngleAxis(Random.value * 360.0f, Vector3.forward);
                    spreadOffset = rot * spreadOffset;
                }

                Vector3 bulletVelocity = Vector3.zero;

                bulletInstance.transform.position = muzzleTransform.position + muzzleTransform.TransformDirection(currentGunData.muzzleOffset);
                bulletInstance.transform.rotation = muzzleTransform.rotation * spreadOffset;

                bulletVelocity = bulletInstance.transform.forward * currentGunData.muzzleVelocity;

                // Add in player velocity if necessary
                if (player != null)
                {
                    bulletVelocity += player.GetVelocity();
                }

                // Notify the bullet it's been fired
                bullet.Fire(damage, currentGunData.damageType, bulletVelocity, gameObject);
            }

            // Spawn effects if available, outside the loop, so there's only ever one
            if (currentGunData.firingEffectsPrefab != null)
            {
                GameObject effectsInstance = GameObject.Instantiate(currentGunData.firingEffectsPrefab);
                effectsInstance.transform.parent        = muzzleTransform;
                effectsInstance.transform.localPosition = currentGunData.firingEffectsOffset;
            }

            // If there's a casing particle, emit 1
            if (optionalCasingParticle != null)
            {
                optionalCasingParticle.Emit(1);
            }

            // Play firing sound if it exists, outside the loop, so there's only ever one
            if (currentGunData.fireSound != null)
            {
                SoundManagerComponent.PlaySound(currentGunData.fireSound, muzzleTransform.gameObject);
            }

            return(BULLET_FIRED);
        }
        else
        {
            return(BULLET_NOT_FIRED);
        }
    }