Back

Capture The Guy Online multiplayer arena game

Meta data

General

NameCapture The Guy
TypeGroup project
Completed2016

Contribution

Programming50%
Design10%
Art0%
Music0%

Technical

EngineUnity 5.3
LanguageC#
NetworkPhoton

About the project

Capture the guy was not the first concept we worked on. Before this one, we have been working on another game. But that concept had a big problem, the scope was way too big, we couldn't finish it. 2 weeks before the deadline we made a decision. We were going to throw the concept away and started on a new concept where we tried to use the assets we already made. We created 'capture the guy' in the remaining 2 weeks of the project. At the end, we were able to use a few of the assets, but unfortunately, we had to throw most of it away. Only some of the AI code was used.

The Gameplay

Our game is about mind control. You can take over a human body and control them. To do this, you need to point at him for 5 seconds, otherwise you would shoot yourself in the nothingness.

The game is called 'capture the guy' because you need to catch one guy. The first player who catches him and sacrifice him in the light, wins the game. Each character you can take over has special ability, except the normal guy, he is just boring. For example the runner can run extremely fast and the fatty is slow, but shoots barriers. In total there are 4 types of characters. When you take over another player, this player is thrown out in to the nothingness. This means that he has to wait 5 seconds and will automatically take over a random, available AI in the arena.

Networking

The networking is made with Photon. This is a plugin and server that takes care of the most basic things. The biggest challenge here was the synchronizing of 40 characters (AI). First, we sent the information of every AI separately in a package. But that was way too slow. At the end, we bundled all positions and rotations of the chapters and sent that in one package. Still not very good, but the deadline was closed and it worked. Now I am wondering if we really needed to sent the position at all. As long as we know where the AI starts and to which waypoint he is walking, the local PC should be able to do the rest. There is maybe the possibility to synchronize the position every few seconds, but it is certainly not needed for every update.

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

using ExitGames.Client.Photon;
using Photon;

public class SyncNetworkTransform : Photon.PunBehaviour {

private const float ANIMATION_SPEED = 20;

public bool sendWhenMaster = false;
public bool sendWhenClient = false;
public bool receiveWhenMaster = false;
public bool receiveWhenClient = false;

private string netowrkID = "";
private RoomPropertiesSync netowrkSync;
private Vector3 targetPos = Vector3.zero;
private Vector3 targetEur = Vector3.zero;
private Vector3 lastPosition = Vector3.zero;


private Animator animator = null;

private void Start () {
netowrkID = "transformOf" + gameObject.name;
netowrkSync = GameObject.FindGameObjectWithTag("Network").GetComponent<RoomPropertiesSync>();
animator = transform.GetChild(0).GetComponent<Animator>();

targetPos = transform.position;
targetEur = transform.eulerAngles;
lastPosition = transform.position;
}

private void Update() {
bool _sendEnabled = (sendWhenMaster && PhotonNetwork.player.IsMasterClient) || (sendWhenClient && !PhotonNetwork.player.IsMasterClient);
bool _receiveEnabled = (receiveWhenMaster && PhotonNetwork.player.IsMasterClient) || (receiveWhenClient && !PhotonNetwork.player.IsMasterClient);

if(_sendEnabled && !transform.position.Equals(lastPosition)) {
string data = transform.position.x + ";" + transform.position.y + ";" + transform.position.z + ";" + transform.eulerAngles.x + ";" + transform.eulerAngles.y + ";" + transform.eulerAngles.z;

if(netowrkSync.hashtable.ContainsKey(netowrkID)) {
Debug.LogError("There are two AI with the same name: " + this.gameObject.name);
} else {
netowrkSync.hashtable.Add(netowrkID, data);
}
}

animator.speed = Vector3.Distance(transform.position, lastPosition) * ANIMATION_SPEED;
lastPosition = transform.position;
}



public override void OnPhotonCustomRoomPropertiesChanged(ExitGames.Client.Photon.Hashtable propertiesThatChanged) {

bool _receiveEnabled = (receiveWhenMaster && PhotonNetwork.player.IsMasterClient) || (receiveWhenClient && !PhotonNetwork.player.IsMasterClient);

if(enabled & propertiesThatChanged.ContainsKey(netowrkID) && _receiveEnabled) {
string _rawData = propertiesThatChanged[netowrkID] as string;

if(_rawData != null && _rawData != "") {
string[] _data = _rawData.Split(';');

transform.position = new Vector3(float.Parse(_data[0]), float.Parse(_data[1]), float.Parse(_data[2]));
transform.eulerAngles = new Vector3(float.Parse(_data[3]), float.Parse(_data[4]), float.Parse(_data[5]));

}

}
}
}

AI

Unfortunately, this was before we learned about AI at the HKU, this is a basic AI that can easily be improved. We created a plug in which we could use to create waypoints in the scene. You can also connect and disconnect waypoints. When the AI is turned on (game starts), they are looking for the closest waypoint and walk towards it. When they are nearby the targeted waypoint, they walk to the next connected waypoint. The next waypoint is selected random out of all the connected points except the one he came from.