DutyCallZ Devlog 1
7 February, 2024
17
17
0
Contributors
So I've recently started working on a new project with one of my friends and the aim of this series of dev logs is going to be to provide a look into the thought process and development of the first-ever full game we're planning on releasing.
The premise of the game is actually rather simple, it will be rather similar to Call of Duty Zombies, a wave-based survival game where the main goal is to survive for as long as possible by killing zombies and accumulating money which then you can use to buy guns and possibly other things from all around the map.
The early plans included buying upgrades for the guns, realistic animations for zombies (such as zombies limping more when you hit their legs or falling down if you hit them too many times consecutively and so on), and buying turrets strategically placed around the map, but of course, these are very long term vision as we plan on keeping this game as simple as we possibly can.
The game will be written in an object-oriented manner as we don't need to utilise ECS for such a simple game.
To start things off, we added the Player into the game. The player has basic control scripts that allow you to control the character and camera movement, as seen below.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[SerializeField] private float speed;
[SerializeField] private CharacterController playerController;
[SerializeField] private float gravity;
[SerializeField] private LayerMask groundMask;
[SerializeField] private Camera playerCamera;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Vector3 lookDirection = Vector3.ProjectOnPlane(playerCamera.transform.forward, Vector3.up).normalized;
bool isGrounded = Physics.Raycast(playerController.transform.position, -transform.up, 1.05f, groundMask);
Vector3 movementDirection = new Vector3(Input.GetAxisRaw("Horizontal"),0, Input.GetAxisRaw("Vertical"));
Quaternion lookDirectionQuaternion = Quaternion.LookRotation(lookDirection);
movementDirection = lookDirectionQuaternion * movementDirection;
if (!isGrounded)
{
movementDirection.y = -gravity;
}
playerController.Move(movementDirection.normalized * (speed * Time.deltaTime));
}
}
The script above has a very simple system that basically just takes the input from the game and changes the players' transform based on it. We take the WASD keys from Input.GetAxisRaw and account for the player's in-game rotation to make sure they are moving forward no matter which way they are looking.
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
public class CameraController : MonoBehaviour
{
[SerializeField] private Camera playerCamera;
[SerializeField] private float mouseSensitivity;
[SerializeField] private Transform playerTransform;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
Cursor.lockState = CursorLockMode.None;
}
float deltaX = Input.GetAxisRaw("Mouse X");
float deltaY = Input.GetAxisRaw("Mouse Y");
var cameraEulerAngles = playerCamera.transform.eulerAngles;
var playerEulerAngles = playerTransform.transform.eulerAngles;
float newRotationY = playerEulerAngles.y + deltaX * Time.deltaTime * mouseSensitivity;
float newRotationX = cameraEulerAngles.x - deltaY * Time.deltaTime * mouseSensitivity;
if (newRotationX is < 270 and > 180)
{
newRotationX = 270;
}
else if (newRotationX is > 90 and < 180)
{
newRotationX = 90;
}
Quaternion newRotationCamera = Quaternion.Euler(newRotationX, newRotationY, 0);
Quaternion newRotationPlayer = Quaternion.Euler(0, newRotationY, 0);
playerCamera.transform.rotation = newRotationCamera;
playerTransform.transform.rotation = newRotationPlayer;
}
}
This part might be a bit more confusing for some. To make sure the player is looking forward all the time and can also look around, we need to work with Euler angles and quaternions. For this part, we thought it would be more appropriate to turn the player's model on the y-axis but turn the camera on the x-axis. So the camera controls looking up and down while the player model controls looking left to right.
We later added zombies to the game. The implementation is actually a lot simpler than some might think thanks to the AI package provided by Unity, which allows us to draw a mesh on the area that can be used by the zombies, making it very easy to make it so that they avoid obstacles while moving towards the player.
The last part of the development was adding a framework for the guns. We added an abstract class called WeaponClass to the game, which will be used as a base for most of the guns in the game. For now, it only has some variables, mostly unused, and 2 functions, Fire and Reload.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class WeaponsClass : MonoBehaviour
{
private float timer;
private bool canShoot;
public float fireCooldown;
public float reloadSpeed;
public float damage;
public float magazineSize;
public float maxAmmo;
public float burstNumber;
public float burstDelay;
[SerializeField] private Camera playerCamera;
[SerializeField] private LayerMask shootingMask;
public virtual void Fire()
{
if (canShoot)
{
RaycastHit objectHit;
Physics.Raycast(playerCamera.transform.position, playerCamera.transform.forward, out objectHit, 999f, shootingMask);
if (objectHit.collider.gameObject.layer == LayerMask.NameToLayer("Zombies"))
{
var zombie = objectHit.collider.gameObject.GetComponent<Zombie>();
zombie.TakeDamage(damage);
}
timer = fireCooldown;
canShoot = false;
}
}
public abstract void Reload();
void Update()
{
if (timer >= 0)
{
timer -= Time.deltaTime;
}
else
{
canShoot = true;
}
}
}
This was the first day of development on our new game, soon to be a wave-based zombie survival game.