Project description

Signalparadox is about Livia Skye who is a military-trained woman in her mid-late 20’s. At the start of the game, Livia finds herself in a room with cryogenic sleeping pods where all the other pods are empty. Livia Skye discovers a ship with it’s crew being wiped and aliens wreaking havoc. Livia makes her way through the ship and finally reaches the escape pods.

  • Sci-fi adventure/thriller
  • Puzzle solving
  • Unique sneak system


Echolocation

We wanted a realisitc soundsystem to make the game more alive and intresting for the sneaking mechanic, so I implemented a echolocation system where the player transmit a signal based on how the player is playing.

The Player and the Distraction granade is both using this script and transmitting a signal. The player has a dynamic system where the strength is based on the movement from the player. The granade has a constant signal. This system is really modular but it's not flawless if the transmitter frequency is set to high this system is not that perfomace light as recomended so I implemented a frequency attribute.

using UnityEngine;
namespace EchoLocation
{
    public class EchoLocationTransmitter : MonoBehaviour
    {
        [SerializeField] private bool debugModeOn, debugTestSoundOn;
        [SerializeField] [Range(1,1000)] private int debugXResolution, debugYResolution, debugMaxBounces;
        [SerializeField] [Range(0f,1f)] private float debugBouncesDecay, debugMinStrengthTolerance, debugAirDecay;
        [SerializeField] private LayerMask debugBounceLayer;

        private void Update()
        {
            if (debugTestSoundOn)
                CreateTestSound();
        }

        private void CreateTestSound()
        {
            CastAudioRays(debugXResolution, debugYResolution, debugMaxBounces, debugBouncesDecay, debugAirDecay, debugMinStrengthTolerance, debugBounceLayer);
        }

        public void CastAudioRays(int xResolution, int yResolution, int maxBounces, float bouncesDecay, float airDecay, float minStrengthTolerance, LayerMask bounceLayer)
        {
            Gizmos.color = Color.red;
            var direction = transform.forward;
            var directionChangeAmount = 360 / xResolution; 
            for (var x = 0; x < xResolution; x++)
            {
                direction = Quaternion.Euler(directionChangeAmount, 0, directionChangeAmount) * direction;
                directionChangeAmount = 360 / yResolution; 
                for (var y = 0; y < yResolution; y++)
                {
                    CastAudioRay(direction, maxBounces, bouncesDecay, airDecay, minStrengthTolerance, bounceLayer);
                    direction = Quaternion.Euler(0, directionChangeAmount, 0) * direction;
                }
            }
        }

        private void CastAudioRay(Vector3 direction, int maxBounces, float bouncesDecay, float airDecay, float minStrengthTolerance, LayerMask bounceLayer)
        {
            var location = transform.position;
            var distance = 0f;
            var strength = 1f;
            for (var i = 0; i < maxBounces; i++)
            {
                Physics.Raycast(location, direction, out var hit, float.PositiveInfinity, bounceLayer);
                if (debugModeOn)
                    Debug.DrawLine(location, hit.point);
                var lastBounceLocation = location;
                location = hit.point;
                direction = Vector3.Reflect(direction, hit.normal);
                distance += hit.distance;
                strength *= 1f - distance * airDecay;
                if(strength < minStrengthTolerance)
                    break;
                if (hit.collider != null && hit.collider.CompareTag("Receiver"))
                {
                    var echoLocationResult = new EchoLocationResult(strength, distance, lastBounceLocation, gameObject, hit.collider.gameObject);
                    hit.collider.GetComponent().ReceiveHit(echoLocationResult);
                }
                strength *= 1 - bouncesDecay;
            }
        }
    }
}
                            
                        

Each enemy has a reciever and if the transmitter is hitting any recivers the reciver will be alerted.

using System;
using UnityEngine;

namespace EchoLocation
{
    public class EchoLocationReceiver : MonoBehaviour
    {
        public Action heardSound;
        public void ReceiveHit(EchoLocationResult echoLocationResult) => heardSound?.Invoke(echoLocationResult);
    }
}