Welcome to GEMENTAR TOUR PUO V2 Development Documentation. Enjoy your stay!

Prototyping Zombie Minigame

Prototyping?

This is the way I make function of models before I make it official.

Player Prototyping

ZombiePlayerController Script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using Micosmo.SensorToolkit;
using System;
using Sirenix.OdinInspector;
using UnityEngine.Events;
using HighlightPlus;
 
public class ZombiePlayerController : MonoBehaviour
{
    [BoxGroup("GameObject Serialization")]
    public GameObject cross;
    [BoxGroup("GameObject Serialization")]
    public Transform charater;
 
    [BoxGroup("DoLookAt Fine Tune")]
    public float lookAtSpeed = 1f;
 
    [BoxGroup("Movement Fine Tune")]
    public float movementSpeed = 1f;
    [BoxGroup("Movement Fine Tune")]
    public float movementSprintSpeed = 1f;
    [BoxGroup("Movement Fine Tune")]
    public float jumpHeight = 1f;
    [BoxGroup("Movement Fine Tune")]
    public float groundGravity = 1f;
    [BoxGroup("Movement Fine Tune")]
    public float runStamina = 15f;
 
    [BoxGroup("Private Variable")]
    [ShowInInspector]
    private bool _groundedStatus;
    [BoxGroup("Private Variable")]
    [ShowInInspector]
    private Vector3 _finalMoveValue;
    [BoxGroup("Private Variable")]
    [ShowInInspector]
    private float _fowardDirection;
    [BoxGroup("Private Variable")]
    [ShowInInspector]
    private float _righDirection;
    [BoxGroup("Private Variable")]
    [ShowInInspector]
    private float _velocity;
    [BoxGroup("Private Variable")]
    [ShowInInspector]
    private float _storedRunStamina;
 
    private CharacterController _characterController;
    private ZombieHealth _zombieHealth;
    private HighlightEffect _highlight;
 
    [HideInEditorMode]
    public UnityEvent<float> sendEventToUI;
 
    [HideInEditorMode]
    public UnityEvent onPlayerDied;
 
    private void Awake()
    {
        Initialization();
    }
 
    private void Start()
    {
        _storedRunStamina = runStamina;
        _zombieHealth.sendEventOnMinusHealth.AddListener(ReceivedEventOnPlayerHit);
        SendEventToUI();
    }
 
    private void Initialization()
    {
        _characterController = this.GetComponent<CharacterController>();
        _zombieHealth = this.GetComponent<ZombieHealth>();
        _highlight = this.GetComponent<HighlightEffect>();
    }
 
    private void Update()
    {
 
        if (_zombieHealth.IsDead())
        {
            onPlayerDied.Invoke();
            return;
        }
 
        _velocity = GetVelocity();
 
        SetRightFowardDirection();
 
        PlayerLookAtCross();
 
        //this will update _movement value that will be called by MovePlayer(_movement);
        SetFinalMoveValue();
 
        MovePlayer(_finalMoveValue);
    }
 
    #region INPUT
    private Vector3 InputRelativeToCamera() 
    {
        //reading the input:
        float horizontalAxis = Input.GetAxis("Horizontal");
        float verticalAxis = Input.GetAxis("Vertical");
 
        //assuming we only using the single camera:
        var camera = Camera.main;
 
        //camera forward and right vectors:
        var forward = camera.transform.forward;
        var right = camera.transform.right;
 
        //project forward and right vectors on the horizontal plane (y = 0)
        forward.y = 0f;
        right.y = 0f;
        forward.Normalize();
        right.Normalize();
 
        //this is the direction in the world space we want to move:
        var desiredMoveDirection = (forward * verticalAxis + right * horizontalAxis).normalized * movementSpeed;
 
        SprintController();
 
        if (Input.GetKey(KeyCode.LeftShift) && runStamina >= 0)
        {
            return desiredMoveDirection * movementSprintSpeed;
        }
 
        return desiredMoveDirection;
    }
 
    private void SprintController()
    {
        SendEventToUI();
 
        if(GetVelocity() > 5)
        {
            runStamina -= Time.deltaTime;
            return;
        }
 
        if (runStamina < _storedRunStamina && GetVelocity() == 0) runStamina += Time.deltaTime;
    }    
 
    private float _jumpDuration = 0;
 
    private float InputMovementJump()
    {
 
        if (!_groundedStatus)
        {
            _jumpDuration -= Time.deltaTime * groundGravity;
        }
        else
        {
            _jumpDuration = Input.GetAxis("Jump");
        }
 
        return _jumpDuration;
    }
    #endregion
 
    #region MONOBEHAVIOUR
    private void SetRightFowardDirection()
    {
        //This method will take dot value to detect character moving direction in local axis (so kalau axis tu rotate dia akan rotate sama)
        _righDirection = Vector3.Dot(transform.right, new Vector3(_finalMoveValue.x, 0f, _finalMoveValue.z));
        _fowardDirection = Vector3.Dot(transform.forward, new Vector3(_finalMoveValue.x, 0, _finalMoveValue.z));
    }
 
    private void PlayerLookAtCross() => charater.DOLookAt(cross.transform.position, lookAtSpeed, AxisConstraint.Y);
 
    private void SetFinalMoveValue()
    {
        Vector3 _moveDirectionAtXZ = InputRelativeToCamera();
        float _jumpDuration = InputMovementJump();
 
        _finalMoveValue = new Vector3(_moveDirectionAtXZ.x, _jumpDuration * jumpHeight, _moveDirectionAtXZ.z);
 
    }
 
    private void MovePlayer(Vector3 _finalMoveValue) =>  _characterController.Move(_finalMoveValue * Time.deltaTime);
    #endregion
 
    #region SET METHOD
    public void SetWhenGrounded() => _groundedStatus = true;
 
    public void SetWhenNotGrounded() =>  _groundedStatus = false;
    #endregion
 
    #region GET METHOD
    public bool IsGroundedStatus() => _groundedStatus;
 
    public bool GetCursor() => Cursor.visible;
 
    public float GetFowardDiretion() => _fowardDirection;
 
    public float GetRightDirection() => _righDirection;
 
    public float GetVelocity() => _characterController.velocity.magnitude;
    #endregion
 
    #region EVENT
    private void InitializeEvent()
    {
        if (sendEventToUI == null) sendEventToUI = new UnityEvent<float>();
        SendEventToUI();
    }
 
    private void SendEventToUI()
    {
        sendEventToUI.Invoke(runStamina);
    }
 
    private void ReceivedEventOnPlayerHit()
    {
        _highlight.HitFX();
    }
    # endregion
}

ZombieGunController Script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Sirenix.OdinInspector;
using HellTap.PoolKit;
using UnityEngine.Events;
using SkyConsole.Utils;
 
public class ZombieGunController : MonoBehaviour
{
    [BoxGroup("GameObject Initialization")]
    public Spawner gunBarrelPoolSpawner;
    [BoxGroup("Weapon Porperties")]
    public float bulletSpeed;
    [BoxGroup("Weapon Porperties")]
    public float shootCooldown = 1f;
    [BoxGroup("Weapon Porperties")]
    private int bullet = 10;
    [BoxGroup("Weapon Porperties")]
    public AudioClip shootSound;
    [BoxGroup("Weapon Porperties")]
    public AudioClip emptyShootSound;
    [BoxGroup("Weapon Porperties")]
    public AudioSource gunSoundSource;
 
    [HideInEditorMode]
    public UnityEvent<int> sendEventToUI;
 
    private void Start()
    {
        gunSoundSource = this.GetComponent<AudioSource>();
        InitializeEvent();
    }
 
    private void Update()
    {
        BulletShootHandler();
    }
 
    [SerializeField]
    private float timer = 0;
    private void BulletShootHandler()
    {
        if (timer > 0)
        {
            timer -= Time.deltaTime;
            return;
        }
 
        if (Input.GetKey(KeyCode.Mouse0))
        {
            timer = shootCooldown;
 
            if (bullet == 0)
            {
                PlaySound(emptyShootSound);
                return;
            }
 
            if (gunBarrelPoolSpawner != null)
            {
                gunBarrelPoolSpawner.Play();
                PlaySound(shootSound);
                bullet -= 1;
                SendEventToUI();
            }
        }
    }
 
    private void PlaySound(AudioClip sound)
    {
        gunSoundSource.PlayOneShot(sound);
    }
 
 
    #region EVENT
    private void InitializeEvent()
    {
        if (sendEventToUI == null) sendEventToUI = new UnityEvent<int>();
        SendEventToUI();
    }
 
    private void SendEventToUI()
    {
        sendEventToUI.Invoke(bullet);
    }
    #endregion
 
    public void addBullet(int bulletCount)
    {
        bullet += bulletCount;
        SendEventToUI();
    }
}

ZombieCameraController Script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Micosmo.SensorToolkit;
using DG.Tweening;
using System;
using Sirenix.OdinInspector;
 
public class ZombieCameraController : MonoBehaviour
{
    [BoxGroup("Serialize GameObject")]
    public GameObject cross;
    [BoxGroup("Serialize GameObject")]
    public GameObject crossCylinder;
    [BoxGroup("Serialize GameObject")]
    public GameObject player;
 
    [BoxGroup("Cross Fine Tuning")]
    public float crossSpeed = 1f;
 
    [BoxGroup("Camera Porperties")]
    public float zTilt;
    [BoxGroup("Camera Porperties")]
    public float xTilt;
 
    private Camera _camera;
    private RaySensor _sensor;
    private RangeSensor _crossRangeSensor;
 
    private void Awake()
    {
        _sensor = this.GetComponent<RaySensor>();
        _camera = this.GetComponent<Camera>();
        _crossRangeSensor = cross.GetComponentInChildren<RangeSensor>();
    }
 
    private void Update()
    {
        MoveRaycastToMousePosition();
        CameraMovement();
        SetCrossCylinderActive();
    }
 
    private void MoveRaycastToMousePosition()
    {
        var ray = _camera.ScreenPointToRay(Input.mousePosition);
        _sensor.Direction = ray.direction;
 
        MoveCrossToRaycastObstructionRayHit();
    }
 
    private void MoveCrossToRaycastObstructionRayHit()
    {
        float x = _sensor.GetObstructionRayHit().Point.x;
        float z = _sensor.GetObstructionRayHit().Point.z;
 
        if (_sensor.IsObstructed) cross.transform.DOMove(new Vector3(x, cross.transform.position.y, z), crossSpeed);
    }
 
    private void CameraMovement()
    {
        this.transform.DOLookAt(player.transform.position, 1f);
 
        float x = player.transform.position.x + xTilt;
        float z = player.transform.position.z + zTilt;
        this.transform.DOMove(new Vector3(x, this.transform.position.y, z), 1f);
    }
 
    private void SetCrossCylinderActive()
    {
        if (_crossRangeSensor.GetNearestDetection() != null)
        {
            crossCylinder.SetActive(true);
        }
        else
        {
            crossCylinder.SetActive(false);
        }
    }
}

ZombieBullet Script

using Micosmo.SensorToolkit;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using HellTap.PoolKit;
using Sirenix.OdinInspector;
using SkyConsole.Utils;
 
public class ZombieBullet : MonoBehaviour
{
    public float bulletSpeed = 25f;
    public ParticleSystem bulletCollideParticle;
    public float bulletDamage = 10;
    public RangeSensor _rangeSensor;
    private MeshRenderer _meshRenderer;
    private Pool _pool;
 
    private bool canMove = true;
 
    private void Awake()
    {
        _meshRenderer = this.GetComponent<MeshRenderer>();
        _pool = FindObjectOfType<Pool>();
 
        _rangeSensor.OnSomeDetection.AddListener(ReceivedListenerOnCollided);
    }
 
    private void Update()
    {
        moveBullet(canMove);
    }
 
    private void moveBullet(bool canMove)
    {
        if(canMove == true) transform.position += transform.forward * Time.deltaTime * bulletSpeed;
    }
 
    private IEnumerator DespawnGameObject(float duration)
    {
 
        yield return new WaitForSeconds(duration);
 
        canMove = true;
        _pool.Despawn(this.gameObject);
    }
 
    #region Called From Event & Outside
    private void ReceivedListenerOnCollided()
    {
        canMove = false;
        bulletCollideParticle.Play();
 
        if(_rangeSensor.GetNearestDetection().TryGetComponent(out ZombieHealth zombieHealth))
        {
            zombieHealth.MinusHealth(bulletDamage);
        }
 
        StartCoroutine(DespawnGameObject(bulletCollideParticle.main.duration));
    }
 
    private void OnDisable()
    {
        _rangeSensor.enabled = false;
    }
 
    private void OnEnable()
    {
        _rangeSensor.enabled = true;
    }
    #endregion
 
}


QR Code
QR Code wiki:prototyping (generated for current page)
Hello World!
DokuWiki with monobook... rules!