You are on page 1of 36

Department of Computer Science & Engineering

IKG PUNJAB TECHNICAL UNIVERSITY MAIN CAMPUS KAPURTHALA

Shooter Arena
a game

By:
Pardeep Kumar : 1818568
Deepak Walia : 1818548
Gurbhej Singh : 1818550
CSE 2018-2022
1
Table of Contents

Serial no. Topic Page


1 About Game 3
2 Benefits of gaming 4
3 Tools used in game 5
4 Approach used 8
5 System requirements 9
6 Game files after build 10
7 Maps in game 11
8 Screen shots from game 12
Scripts:
➢ Player controller
script
➢ Gun script
➢ Level script
➢ Main menu script
➢ Pause screen script
➢ Target movement
script
➢ UI controller script
9 14
➢ Victory screen
script
➢ Game Manager
script
➢ Enemy Controller
script

9 Credits 34

2
ABOUT GAME !

This Game is purely for entertainment purpose, an ongoing project created in Unity
3D. the whole idea is based on Theme of Alien Invasion environment. This First-
Person Shooter game themed on Minecraft Graphics Structured on basic design,
simple Graphics. No heavy graphics components are being used in the Game.
Game can run on Simple System aka’ low end system. The Game is developed
using Unity 3D, Blender and Visual Studio 2019. whole code and documentation
later explained in this document of project Report. Every resource is enclosed
along the document and URLs are enclosed.

Why we created this Game!


we want to experience the Unity 3D game development, and we want to create our
own game without any license, so we don’t need to crack it and exploring the
whole unity game development so that we can be able to work on other game
engines like Unreal Engine 4, DUNIA engine, amazon lumberyard, CryEngine &
many more popular engines in the world of game development. Game can be
Buggy as we are not professional builders and there other loopholes in our game so
we are working on it as you already read its an ongoing Project.

3
Benefits of gaming !

▪ Improved cognitive abilities


▪ Improved problem-solving skills and logic
▪ Increased hand-to-eye coordination
▪ Greater multi-tasking ability
▪ Faster and more accurate decision-making
▪ Enhanced prosocial behaviors
▪ Better eyesight (attention to detail)
▪ More physical activity with games that promote physical activity
(VR, mobile games)
▪ And other benefits.

as it already said, excess of everything is bad So, don’t overplay it, By the
way it’s already a three-mission game !

4
Tools used in Game Development

Unity is, simply put, the world’s most popular game engine. It packs a ton of
features together and is flexible enough to make almost any game you can imagine.

With unrivaled cross-platform features, Unity is popular with both hobby developers
and AAA studios. It’s been used to create games like Pokémon Go, Heathstone, Rim
world, Cuphead, and plenty more.

While 3D is in the name, Unity 3D also packs tools for 2D game development.
Programmers love it because of the C# scripting API and built-in Visual Studio
integration. Unity also offers JavaScript as a scripting language
and MonoDevelop as an IDE to those who want an alternative to Visual Studio.

Unity is, simply put, the world’s most popular game engine. It packs a ton of features
together and is flexible enough to make almost any game you can imagine. With
unrivaled cross-platform features, Unity is popular with both hobby developers and
AAA studios. It’s been used to create games like Pokémon Go, Hearthstone, Rim
world, Cuphead, and plenty more.

While 3D is in the name, Unity 3D also packs tools for 2D game development.

5
Programmers love it because of the C# scripting API and built-in Visual Studio
integration. Unity also offers JavaScript as a scripting language
and MonoDevelop as an IDE to those who want an alternative to Visual Studio.

Visual Studio 2019

Visual Studio is one of the most famous IDEs has been using for the last few years.
Microsoft developed it. It is used to create a computer program, web applications,
and EXE files, etc. The first version of its kind was launched in 1997. And now the
latest version available in the market is Visual Studio 2019. Visual Studio 2019 was
released on April 2nd, 2019. There are so many advanced features that will be
included in this version.

The Visual Studio IDE (integrated development


environment) is a software program for developers to write and edit their code. Its
user interface is used for software development to edit, debug and build code. Visual
Studio includes a code editor supporting IntelliSense (the code completion
component) as well as code refactoring. The integrated debugger works both as a
source-level debugger and a machine-level debugger. Other built-in tools include a
code profiler, designer for building GUI applications, web designer, class designer,
and database schema designer. Incredibuild accelerates Visual Studio C++
builds by distributing compilation tasks across machines in the network or public
cloud, thus scaling the building machine to hundreds of cores. Since 2015,
Incredibuild is bundled as part of Visual Studio, once installed directly from within
Visual Studio, Incredibuild appears in the Visual Studio menu. All you need to do is
choose one of Visual Studio C++ workloads: desktop development with C++, game
development with C++ and Mobile development with C++ and check the
‘Incredibuild – Build acceleration’ check box. If you already chosen your workloads,

6
choose the ‘modify’ option and in the workload screen check the ‘Incredibuild –
Build acceleration’ checkbox.

Blender

Blender is the free and open-source 3D creation suite. It supports the entirety of the
3D pipeline—modeling, rigging, animation, simulation, rendering, compositing and
motion tracking, even video editing and game creation. Advanced users employ
Blender’s API for Python scripting to customize the application and write
specialized tools; often these are included in Blender’s future releases. Blender is
well suited to individuals and small studios who benefit from its unified pipeline and
responsive development process. Examples from many Blender-based projects are
available in the showcase.

Blender is cross-platform and runs equally well on Linux, Windows, and Macintosh
computers. Its interface uses OpenGL to provide a consistent experience. To confirm
specific compatibility, the list of supported platforms indicates those regularly tested
by the development team.

As a community-driven project under the GNU General Public License (GPL), the
public is empowered to make small and large changes to the code base, which leads
to new features, responsive bug fixes, and better usability. Blender has no price tag,
but you can invest, participate, and help to advance a powerful collaborative tool:
Blender is your own 3D software.

7
Approach used

Test screen
setup

Prepared Scripts
using C# for each
Object or Asset taken
in Game using Visual
studio
8
System Requirements
• Version: 1.0
• Product Name: Shooter Arena
• CPU: i3 4th generation
• RAM: 2 GB
• OS: Windows 7, Windows 8.1, Windows 10 x86_64
• GPU: No GPU Required
• DirectX Must required to play without errors!

Script Files

9
Game files after Build

10
Maps Included in game
*Dusk Crawl

This map is based on the alien themed imagination. The prefabs


created elements been used in the designing of this map. Every
element used in the map has its own programming controller
scripts programmed in C#.at the end of every map, there is been
a door which leads player to the next level, to cross this door there
has been giant enemy. Player needs to defeat these Giants to win
this game with every level the games become hard. The difficulty
of game simply depends on the health value of the enemies and
of our own player. There has been variable associated with the
enemies “Current Health” with different enemy the value of the
variable is different based on the difficulty of level.

11
Enemy variable:

enemy health controller variable

Scenes directory of game

12
*Pirate Kit

This map is based on the Space Pirate themed imagination. The


prefabs created elements been used in the designing of this map.
Every element used in the map has its own programming
controller scripts programmed in C#.at the end of every map,
there is been a door which leads player to the next level, to cross
this door there has been giant enemy. Player needs to defeat these
Giants to win this game with every level the games become hard.
The difficulty of game simply depends on the health value of the
enemies and of our own player. There has been variable
associated with the enemies “Current Health” with different
enemy the value of the variable is different based on the difficulty
of level.

13
Screenshots from game

14
15
Script Codes

Player Controller

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour


{
public static PlayerController instance;

public float moveSpeed, gravityModifier, jumpPower, runSpeed = 12f;


public CharacterController charCon;

private Vector3 moveInput;

public Transform camTrans;

public float mouseSensitivity;


public bool invertX;
public bool invertY;

private bool canJump, canDoubleJump;


public Transform groundCheckPoint;
public LayerMask whatIsGround;

public Animator anim;

//public GameObject bullet;


public Transform firePoint;

public Gun activeGun;


public List<Gun> allGuns = new List<Gun>();
public List<Gun> unlockableGuns = new List<Gun>();
public int currentGun;

public Transform adsPoint, gunHolder;


private Vector3 gunStartPos;
public float adsSpeed = 2f;

public GameObject muzzleFlash;

public AudioSource footstepFast, footstepSlow;

private float bounceAmount;


private bool bounce;

private void Awake()


{
instance = this;
}

16
// Start is called before the first frame update
void Start()
{
currentGun--;
SwitchGun();

gunStartPos = gunHolder.localPosition;
}

// Update is called once per frame


void Update()
{
if (!UIController.instance.pauseScreen.activeInHierarchy &&
!GameManager.instance.levelEnding)
{
//moveInput.x = Input.GetAxis("Horizontal") * moveSpeed * Time.deltaTime;
//moveInput.z = Input.GetAxis("Vertical") * moveSpeed * Time.deltaTime;

//store y velocity
float yStore = moveInput.y;

Vector3 vertMove = transform.forward * Input.GetAxis("Vertical");


Vector3 horiMove = transform.right * Input.GetAxis("Horizontal");

moveInput = horiMove + vertMove;


moveInput.Normalize();

if (Input.GetKey(KeyCode.LeftShift))
{
moveInput = moveInput * runSpeed;
}
else
{
moveInput = moveInput * moveSpeed;
}

moveInput.y = yStore;

moveInput.y += Physics.gravity.y * gravityModifier * Time.deltaTime;

if (charCon.isGrounded)
{
moveInput.y = Physics.gravity.y * gravityModifier * Time.deltaTime;
}

canJump = Physics.OverlapSphere(groundCheckPoint.position, .25f,


whatIsGround).Length > 0;

if (canJump)
{
canDoubleJump = false;
}

//Handle Jumping
if (Input.GetKeyDown(KeyCode.Space) && canJump)
{
moveInput.y = jumpPower;

17
canDoubleJump = true;

AudioManager.instance.PlaySFX(8);
}
else if (canDoubleJump && Input.GetKeyDown(KeyCode.Space))
{
moveInput.y = jumpPower;

canDoubleJump = false;

AudioManager.instance.PlaySFX(8);
}

if(bounce)
{
bounce = false;
moveInput.y = bounceAmount;

canDoubleJump = true;

charCon.Move(moveInput * Time.deltaTime);

//control camera rotation


Vector2 mouseInput = new Vector2(Input.GetAxisRaw("Mouse X"),
Input.GetAxisRaw("Mouse Y")) * mouseSensitivity;

if (invertX)
{
mouseInput.x = -mouseInput.x;
}
if (invertY)
{
mouseInput.y = -mouseInput.y;
}

transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x,
transform.rotation.eulerAngles.y + mouseInput.x, transform.rotation.eulerAngles.z);

camTrans.rotation = Quaternion.Euler(camTrans.rotation.eulerAngles + new


Vector3(-mouseInput.y, 0f, 0f));

muzzleFlash.SetActive(false);

//Handle Shooting
//single shots
if (Input.GetMouseButtonDown(0) && activeGun.fireCounter <= 0)
{
RaycastHit hit;
if (Physics.Raycast(camTrans.position, camTrans.forward, out hit, 50f))
{
if (Vector3.Distance(camTrans.position, hit.point) > 2f)
{

18
firePoint.LookAt(hit.point);
}
}
else
{
firePoint.LookAt(camTrans.position + (camTrans.forward * 30f));
}

//Instantiate(bullet, firePoint.position, firePoint.rotation);


FireShot();
}

//repeating shots
if (Input.GetMouseButton(0) && activeGun.canAutoFire)
{
if (activeGun.fireCounter <= 0)
{
FireShot();
}
}

if (Input.GetKeyDown(KeyCode.Tab))
{
SwitchGun();
}

if (Input.GetMouseButtonDown(1))
{
CameraController.instance.ZoomIn(activeGun.zoomAmount);
}

if (Input.GetMouseButton(1))
{
gunHolder.position = Vector3.MoveTowards(gunHolder.position,
adsPoint.position, adsSpeed * Time.deltaTime);
}
else
{
gunHolder.localPosition = Vector3.MoveTowards(gunHolder.localPosition,
gunStartPos, adsSpeed * Time.deltaTime);
}

if (Input.GetMouseButtonUp(1))
{
CameraController.instance.ZoomOut();
}

anim.SetFloat("moveSpeed", moveInput.magnitude);
anim.SetBool("onGround", canJump);

}
}

19
public void FireShot()
{
if (activeGun.currentAmmo > 0)
{

activeGun.currentAmmo--;

Instantiate(activeGun.bullet, firePoint.position, firePoint.rotation);

activeGun.fireCounter = activeGun.fireRate;

UIController.instance.ammoText.text = "AMMO: " + activeGun.currentAmmo;

muzzleFlash.SetActive(true);
}
}

public void SwitchGun()


{
activeGun.gameObject.SetActive(false);

currentGun++;

if(currentGun >= allGuns.Count)


{
currentGun = 0;
}

activeGun = allGuns[currentGun];
activeGun.gameObject.SetActive(true);

UIController.instance.ammoText.text = "AMMO: " + activeGun.currentAmmo;

firePoint.position = activeGun.firepoint.position;
}

public void AddGun(string gunToAdd)


{
bool gunUnlocked = false;

if(unlockableGuns.Count > 0)
{
for(int i = 0; i < unlockableGuns.Count; i++)
{
if(unlockableGuns[i].gunName == gunToAdd)
{
gunUnlocked = true;

allGuns.Add(unlockableGuns[i]);

unlockableGuns.RemoveAt(i);

i = unlockableGuns.Count;
}
}

20
if(gunUnlocked)
{
currentGun = allGuns.Count - 2;
SwitchGun();
}
}

public void Bounce(float bounceForce)


{
bounceAmount = bounceForce;
bounce = true;
}
}

Gun Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gun : MonoBehaviour


{
public GameObject bullet;

public bool canAutoFire;

public float fireRate;


[HideInInspector]
public float fireCounter;

public int currentAmmo, pickupAmount;

public Transform firepoint;

public float zoomAmount;

public string gunName;

// Start is called before the first frame update


void Start()
{

// Update is called once per frame


void Update()
{
if(fireCounter > 0)
{
fireCounter -= Time.deltaTime;
}
}

public void GetAmmo()


{
currentAmmo += pickupAmount;

21
UIController.instance.ammoText.text = "AMMO: " + currentAmmo;
}
}

LeveExit.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class LevelExit : MonoBehaviour


{
public string nextLevel;

public float waitToEndLevel;

// Start is called before the first frame update


void Start()
{

// Update is called once per frame


void Update()
{

private void OnTriggerEnter(Collider other)


{
if(other.tag == "Player")
{
GameManager.instance.levelEnding = true;

StartCoroutine(EndLevelCo());

AudioManager.instance.PlayLevelVictory();
}
}

private IEnumerator EndLevelCo()


{
PlayerPrefs.SetString(nextLevel + "_cp", "");
PlayerPrefs.SetString("CurrentLevel", nextLevel);

yield return new WaitForSeconds(waitToEndLevel);

SceneManager.LoadScene(nextLevel);
}
}

22
Main Menu
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class MainMenu : MonoBehaviour


{
public string firstLevel;

public GameObject continueButton;

// Start is called before the first frame update


void Start()
{
if(PlayerPrefs.HasKey("CurrentLevel"))
{
if(PlayerPrefs.GetString("CurrentLevel") == "")
{
continueButton.SetActive(false);
}
} else
{
continueButton.SetActive(false);
}
}

// Update is called once per frame


void Update()
{

public void Continue()


{
SceneManager.LoadScene(PlayerPrefs.GetString("CurrentLevel"));
}

public void PlayGame()


{
SceneManager.LoadScene(firstLevel);

PlayerPrefs.SetString("CurrentLevel", "");

PlayerPrefs.SetString(firstLevel + "_cp", "");


}

public void QuitGame()


{
Application.Quit();
Debug.Log("Quitting Game");
}
}

23
Pause Screen
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class MainMenu : MonoBehaviour


{
public string firstLevel;

public GameObject continueButton;

// Start is called before the first frame update


void Start()
{
if(PlayerPrefs.HasKey("CurrentLevel"))
{
if(PlayerPrefs.GetString("CurrentLevel") == "")
{
continueButton.SetActive(false);
}
} else
{
continueButton.SetActive(false);
}
}

// Update is called once per frame


void Update()
{

public void Continue()


{
SceneManager.LoadScene(PlayerPrefs.GetString("CurrentLevel"));
}

public void PlayGame()


{
SceneManager.LoadScene(firstLevel);

PlayerPrefs.SetString("CurrentLevel", "");

PlayerPrefs.SetString(firstLevel + "_cp", "");


}

public void QuitGame()


{
Application.Quit();
Debug.Log("Quitting Game");
}
}

24
Target Movement
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TargetMovement : MonoBehaviour


{
public bool shouldMove, shouldRotate;

public float moveSpeed, rotateSpeed;

// Start is called before the first frame update


void Start()
{

// Update is called once per frame


void Update()
{
if(shouldMove)
{
transform.position += new Vector3(moveSpeed, 0f, 0f) * Time.deltaTime;
}

if(shouldRotate)
{
transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles + new
Vector3(0f, rotateSpeed * Time.deltaTime, 0f));
}
}
}

25
UI controller
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TargetMovement : MonoBehaviour


{
public bool shouldMove, shouldRotate;

public float moveSpeed, rotateSpeed;

// Start is called before the first frame update


void Start()
{

// Update is called once per frame


void Update()
{
if(shouldMove)
{
transform.position += new Vector3(moveSpeed, 0f, 0f) * Time.deltaTime;
}

if(shouldRotate)
{
transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles + new
Vector3(0f, rotateSpeed * Time.deltaTime, 0f));
}
}
}

26
Victory Screen
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class VictoryScreen : MonoBehaviour


{
public string mainMenuScene;

public float timeBetweenShowing = 1f;

public GameObject textBox, returnButton;

public Image blackScreen;


public float blackScreenFade = 2f;

// Start is called before the first frame update


void Start()
{
StartCoroutine(ShowObjectsCo());

Cursor.lockState = CursorLockMode.None;
}

// Update is called once per frame


void Update()
{
blackScreen.color = new Color(blackScreen.color.r, blackScreen.color.g,
blackScreen.color.b, Mathf.MoveTowards(blackScreen.color.a, 0f, blackScreenFade *
Time.deltaTime));
}

public void MainMenu()


{
SceneManager.LoadScene(mainMenuScene);
}

public IEnumerator ShowObjectsCo()


{
yield return new WaitForSeconds(timeBetweenShowing);

textBox.SetActive(true);

yield return new WaitForSeconds(timeBetweenShowing);

returnButton.SetActive(true);
}
}

27
Game Manager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour


{
public static GameManager instance;

public float waitAfterDying = 2f;

[HideInInspector]
public bool levelEnding;

private void Awake()


{
instance = this;
}

// 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))
{
PauseUnpause();
}
}

public void PlayerDied()


{
StartCoroutine(PlayerDiedCo());

public IEnumerator PlayerDiedCo()


{
yield return new WaitForSeconds(waitAfterDying);

SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}

public void PauseUnpause()


{
if(UIController.instance.pauseScreen.activeInHierarchy)
{
UIController.instance.pauseScreen.SetActive(false);

Cursor.lockState = CursorLockMode.Locked;

28
Time.timeScale = 1f;

PlayerController.instance.footstepFast.Play();
PlayerController.instance.footstepSlow.Play();
} else
{
UIController.instance.pauseScreen.SetActive(true);

Cursor.lockState = CursorLockMode.None;

Time.timeScale = 0f;

PlayerController.instance.footstepFast.Stop();
PlayerController.instance.footstepSlow.Stop();
}
}
}

29
Enemy Controller
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class EnemyController : MonoBehaviour


{

private bool chasing;


public float distanceToChase = 10f, distanceToLose = 15f, distanceToStop = 2f;

private Vector3 targetPoint, startPoint;

public NavMeshAgent agent;

public float keepChasingTime = 5f;


private float chaseCounter;

public GameObject bullet;


public Transform firePoint;

public float fireRate, waitBetweenShots = 2f, timeToShoot = 1f;


private float fireCount, shotWaitCounter, shootTimeCounter;

public Animator anim;

private bool wasShot;

// Start is called before the first frame update


void Start()
{
startPoint = transform.position;

shootTimeCounter = timeToShoot;
shotWaitCounter = waitBetweenShots;
}

// Update is called once per frame


void Update()
{
targetPoint = PlayerController.instance.transform.position;
targetPoint.y = transform.position.y;

if (!chasing)
{
if (Vector3.Distance(transform.position, targetPoint) < distanceToChase)
{
chasing = true;

shootTimeCounter = timeToShoot;
shotWaitCounter = waitBetweenShots;
}

if (chaseCounter > 0)
{

30
chaseCounter -= Time.deltaTime;

if (chaseCounter <= 0)
{
agent.destination = startPoint;
}
}

if(agent.remainingDistance < .25f)


{
anim.SetBool("isMoving", false);
} else
{
anim.SetBool("isMoving", true);
}
}
else
{

if (Vector3.Distance(transform.position, targetPoint) > distanceToStop)


{
agent.destination = targetPoint;
} else
{
agent.destination = transform.position;
}

if(Vector3.Distance(transform.position, targetPoint) > distanceToLose)


{
if (!wasShot)
{
chasing = false;

chaseCounter = keepChasingTime;
}
} else
{
wasShot = false;
}

if (shotWaitCounter > 0)
{
shotWaitCounter -= Time.deltaTime;

if(shotWaitCounter <= 0)
{
shootTimeCounter = timeToShoot;
}

anim.SetBool("isMoving", true);
} else {

if (PlayerController.instance.gameObject.activeInHierarchy)
{

shootTimeCounter -= Time.deltaTime;

31
if (shootTimeCounter > 0)
{
fireCount -= Time.deltaTime;

if (fireCount <= 0)
{
fireCount = fireRate;

firePoint.LookAt(PlayerController.instance.transform.position
+ new Vector3(0f, 1.2f, 0f));

Vector3 targetDir =
PlayerController.instance.transform.position - transform.position;
float angle = Vector3.SignedAngle(targetDir,
transform.forward, Vector3.up);

if (Mathf.Abs(angle) < 30f)


{

Instantiate(bullet, firePoint.position,
firePoint.rotation);

anim.SetTrigger("fireShot");
}
else
{
shotWaitCounter = waitBetweenShots;
}
}

agent.destination = transform.position;
}
else
{
shotWaitCounter = waitBetweenShots;
}
}

anim.SetBool("isMoving", false);
}
}
}

public void GetShot()


{
wasShot = true;

chasing = true;
}
}

32
Camera Controller
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraController : MonoBehaviour


{
public static CameraController instance;

public Transform target;

private float startFOV, targetFOV;

public float zoomSpeed = 1f;

public Camera theCam;

private void Awake()


{
instance = this;
}

// Start is called before the first frame update


void Start()
{
startFOV = theCam.fieldOfView;
targetFOV = startFOV;
}

// Update is called once per frame


void LateUpdate()
{
transform.position = target.position;
transform.rotation = target.rotation;

theCam.fieldOfView = Mathf.Lerp(theCam.fieldOfView, targetFOV, zoomSpeed *


Time.deltaTime);
}

public void ZoomIn(float newZoom)


{
targetFOV = newZoom;
}

public void ZoomOut()


{
targetFOV = startFOV;
}
}

33
Bullet Controller
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BulletController : MonoBehaviour


{
public float moveSpeed, lifeTime;

public Rigidbody theRB;

public GameObject impactEffect;

public int damage = 1;

public bool damageEnemy, damagePlayer;

// Start is called before the first frame update


void Start()
{

// Update is called once per frame


void Update()
{
theRB.velocity = transform.forward * moveSpeed;

lifeTime -= Time.deltaTime;

if(lifeTime <= 0)
{
Destroy(gameObject);
}
}

private void OnTriggerEnter(Collider other)


{
if(other.gameObject.tag == "Enemy" && damageEnemy)
{

other.gameObject.GetComponent<EnemyHealthController>().DamageEnemy(damage);
}

if(other.gameObject.tag == "Headshot" && damageEnemy)


{

other.transform.parent.GetComponent<EnemyHealthController>().DamageEnemy(damage * 2);
Debug.Log("Headshot hit");
}

if(other.gameObject.tag == "Player" && damagePlayer)


{

PlayerHealthController.instance.DamagePlayer(damage);
}

34
Destroy(gameObject);
Instantiate(impactEffect, transform.position + (transform.forward * (-moveSpeed *
Time.deltaTime)), transform.rotation);
}
}

35
Credits n Sources
https://www.blender.org/
https://visualstudio.microsoft.com/vs/
https://unity.com/
https://www.udemy.com/
Assets :
https://kenney.nl/
https://assetstore.unity.com/packages/tools/game-toolkits/game-creator-2-
203069?aid=1100l36uR&utm_campaign=unity_affiliate&utm_medium=affiliate&
utm_source=partnerize-linkmaker

36

You might also like