How can I edit the c# code to show that player 1 or 2 won when the other player dies. And show the dead player that they lost?
PlayerController Script
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
namespace S3
{
public class PlayerController : NetworkBehaviour {
public GameObject bulletPrefab;
public Transform bulletSpawn;
// Update is called once per frame
void Update ()
{
if (!isLocalPlayer) {
return;
}
float x = Input.GetAxis ("Horizontal") * Time.deltaTime * 150.0f;
float z = Input.GetAxis ("Vertical") * Time.deltaTime * 3.0f;
transform.Rotate (0, x, 0);
transform.Translate (0, 0, z);
if (Input.GetKeyDown (KeyCode.Space))
{
CmdFire();
}
}
[Command]
void CmdFire()
{
GameObject bullet = (GameObject) Instantiate(bulletPrefab, bulletSpawn.position, bulletSpawn.rotation);
bullet.GetComponent<Rigidbody> ().velocity = bullet.transform.forward * 6.0f;
NetworkServer.Spawn(bullet);
Destroy (bullet, 2);
}
public override void OnStartLocalPlayer()
{
GetComponent<MeshRenderer> ().material.color = Color.blue;
}
}
}
Health Script
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
namespace S3
{
public class Health : NetworkBehaviour {
public const int maxHealth = 100;
[SyncVar (hook = "OnChangeHealth")]public int currentHealth = maxHealth;
public RectTransform healthbar;
public void TakeDamage(int amount)
{
if (!isServer)
{
return;
}
currentHealth -= amount;
if (currentHealth <= 0)
{
currentHealth = maxHealth;
RpcRespawn();
}
}
void OnChangeHealth(int health)
{
healthbar.sizeDelta = new Vector2(health * 2, healthbar.sizeDelta.y);
}
[ClientRpc]
void RpcRespawn()
{
if(isLocalPlayer)
{
transform.position = Vector3.zero;
}
}
}
}
This is the codeaspğlasdlişsadlşisadlşiadsilşdslaişdlasişlişdsacdl işsadilşaLDİŞaslişÖDASİÖŞLDÖİLSAŞDöliasödilascöildaiölşsdöiaşsdöilasödilasiöldasöildasöildöilasdöilaöildöildasöildaöilsdöilasdölasdöliasölidasöildsaöildsöiladiösladöilsadöilsadöilasdiölsadiölsaöidlsaöildsöidiösladiölsadiölsadöilasöild
You can send a Command to the server with netID of the player who have won and check in RPC if the netID matches.
If netID matches for the local player then, he is the winner. Otherwise, he loses. Haven't tested the code below but should work:
[Command]
public void CmdGameWon()
{
RpcGameEnd(this.netId);
}
[ClientRpc]
public void RpcGameEnd(NetworkInstanceId nid)
{
if(this.isLocalPlayer && this.netId==nid){
//Process win here
}else{
//Process lose here
}
}
Related
I have followed this tutorial multiplayer fps serie from Expressed Unity especially this episode "https://youtu.be/j9PC9RhurRI?list=PLD4OdGjxbaByCEOH3fOJ4MgOdROHHBKUo" and i need some help with it.
I have followed the video till 23:30 and then all sort of things are broken. I get error saying "Can not Instantiate before client joined/created a room. State: Joining." and i dont know what i should to do.
I have checked all the codes and everything but for nothing. Do you have solution? I don't which code have the problem so i copy all three of the codes i have edited following this video.
MpManager script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine.SceneManagement;
public class MPManager : MonoBehaviourPunCallbacks
{
public GameObject[] EnableObjectsOnConnect;
public GameObject[] DisableObjectsOnConnect;
// Start is called before the first frame update
void Start()
{
PhotonNetwork.ConnectUsingSettings();
//PhotonNetwork.ConnectToRegion("eu");
}
public override void OnConnectedToMaster()
{
foreach(GameObject obj in EnableObjectsOnConnect)
{
obj.SetActive(true);
}
foreach(GameObject obj in DisableObjectsOnConnect)
{
obj.SetActive(false);
}
Debug.Log("Connected to photon");
}
public void JoinFFA()
{
PhotonNetwork.AutomaticallySyncScene = true;
PhotonNetwork.JoinRandomRoom();
}
public override void OnJoinRandomFailed(short returnCode, string message)
{
CreateFFA();
}
public void CreateFFA()
{
PhotonNetwork.AutomaticallySyncScene = true;
RoomOptions ro = new RoomOptions { MaxPlayers = 10, IsOpen = true, IsVisible = true };
PhotonNetwork.CreateRoom("defaultFFA", ro, TypedLobby.Default);
SceneManager.LoadScene("FFA");
}
}
Movement script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon;
using Photon.Pun;
public class Movement : MonoBehaviourPun
{
public KeyCode Left;
public KeyCode Right;
public KeyCode Forward;
public KeyCode Backward;
[SerializeField]
private float MoveSpeed = 50;
private Rigidbody body;
private GameObject cam;
// Start is called before the first frame update
void Start()
{
body = GetComponent<Rigidbody>();
cam = gameObject.transform.GetChild(0).gameObject;
if (photonView.IsMine)
{
cam.SetActive(true);
}
}
// Update is called once per frame
void Update()
{
if (photonView.IsMine)
{
float x = Input.GetAxis("Mouse X");
float y = Input.GetAxis("Mouse Y");
if (Input.GetKey(Left))
{
body.AddRelativeForce(Vector3.left * MoveSpeed, ForceMode.Impulse);
}
if (Input.GetKey(Right))
{
body.AddRelativeForce(Vector3.left * -MoveSpeed, ForceMode.Impulse);
}
if (Input.GetKey(Forward))
{
body.AddRelativeForce(Vector3.forward * MoveSpeed, ForceMode.Impulse);
}
if (Input.GetKey(Backward))
{
body.AddRelativeForce(Vector3.forward * -MoveSpeed, ForceMode.Impulse);
}
gameObject.transform.Rotate(new Vector3(0, x, 0));
cam.transform.Rotate(new Vector3(-y, 0, 0));
}
}
}
FFa script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon;
using Photon.Pun;
public class FFA : MonoBehaviourPun, IPunObservable
{
public float SpawnTime;
float timer;
bool HasPlayerSpawned = false;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
timer += Time.deltaTime;
if(timer >= SpawnTime)
{
if (!HasPlayerSpawned)
{
PhotonNetwork.Instantiate("Player", Vector3.zero, Quaternion.identity, 0);
HasPlayerSpawned = true;
}
timer = 0;
}
}
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
{
if(stream.IsWriting)
{
}else if (stream.IsReading)
{
}
}
}
Sorry if I had typos my english not good.
Solution found! i just made the spawntime to 1 second instead of 0 so the player had time to join room before instantiating.
I'm new to unity and I'm trying to make an isometric 3d game, but I have some problem, I would like that the player stops moving when I stop using the virtual joystick. Here's my 2 scripts for movement. The first one is in the virtual joystick to make it move and the second one is in the player and make it move in the direction of the joystick.
Joystick script:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
public class VirtualJoystick : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler
{
private Image bgImg;
private Image joystickImg;
private Vector3 inputVector;
private void Start()
{
bgImg = GetComponent<Image>();
joystickImg = transform.GetChild(0).GetComponent<Image>();
}
public virtual void OnDrag(PointerEventData ped)
{
Vector2 pos;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(bgImg.rectTransform, ped.position, ped.pressEventCamera, out pos))
{
pos.x = (pos.x / bgImg.rectTransform.sizeDelta.x);
pos.y = (pos.y / bgImg.rectTransform.sizeDelta.x);
inputVector = new Vector3(pos.x * 2 + 1, 0, pos.y * 2 - 1);
inputVector = (inputVector.magnitude > 1.0f) ? inputVector.normalized : inputVector;
// Move joystickImg
joystickImg.rectTransform.anchoredPosition =
new Vector3(inputVector.x * bgImg.rectTransform.sizeDelta.x / 3
, inputVector.z * (bgImg.rectTransform.sizeDelta.y / 3));
}
}
public virtual void OnPointerDown(PointerEventData ped)
{
OnDrag(ped);
}
public virtual void OnPointerUp(PointerEventData ped)
{
inputVector = Vector3.zero;
joystickImg.rectTransform.anchoredPosition = Vector3.zero;
}
public float Horizontal()
{
if (inputVector.x != 0)
return inputVector.x;
else
return Input.GetAxis("Horizontal");
}
public float Vertical()
{
if (inputVector.x != 0)
return inputVector.z;
else
return Input.GetAxis("Vertical");
}
}
Player Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour
{
public float moveSpeed = 20f;
public VirtualJoystick moveJoystick;
private void Update()
{
Vector3 dir = Vector3.zero;
dir.x = moveJoystick.Horizontal();
dir.z = moveJoystick.Vertical();
GetComponent<Rigidbody>().AddForce(dir * moveSpeed);
}
}
For stopping the player when you let go of the virtual joystick, we can tell the player's rigidbody to sleep. This will make the player halt until another force is added to it.
Update your Player script to the following:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour
{
public float moveSpeed = 20f;
public VirtualJoystick moveJoystick;
public Rigidbody rb;
private Vector3 dir = Vector3.zero;
private bool wasMoving = false;
private void Update()
{
dir.x = moveJoystick.Horizontal();
dir.z = moveJoystick.Vertical();
if (dir.magnitude > 0)
{
wasMoving = true;
}
}
private void FixedUpdate()
{
if (wasMoving && dir.magnitude == 0f)
{
wasMoving = false;
rb.Sleep();
}
rb.AddForce(dir * moveSpeed);
}
}
It's also a good idea to store the Rigidbody as a variable so you don't recompute it every update. Be sure to drag it into the script from the inspector.
I am trying to make my camera rotate right around the gameobject it is assigned to. So far I can get it to rotate around the gameobject, but it is rotating left not right. Any help is appreciated. Here is my code.
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
public class CameraRotate : MonoBehaviour
{
public float speed;
float time = 5.0f;
public bool updateOn = true;
void Start()
{
StartCoroutine(updateOff());
}
void Update()
{
if (updateOn == true)
{
if (time >= 0)
{
time -= Time.deltaTime;
return;
}
else
{
transform.Rotate(0, speed * Time.deltaTime, 0);
}
}
}
IEnumerator updateOff()
{
yield return new WaitForSeconds(10.0f);
updateOn = false;
}
}
using UnityEngine;
using System.Collections;
public class CameraRotate : MonoBehaviour
{
public float speed;
float time = 5.0f;
public bool updateOn = true;
void Start()
{
StartCoroutine(updateOff());
}
void Update()
{
if (updateOn == true)
{
if (time >= 0)
{
time -= Time.deltaTime;
return;
}
else
{
transform.Rotate(0, -speed * Time.deltaTime, 0);
}
}
}
IEnumerator updateOff()
{
yield return new WaitForSeconds(10.0f);
updateOn = false;
}
}
I am extremely close to finishing my game, every code I posted works well but I want my player to die whether it collides with the box (which is the enemy). However, I've tried to do some research and I can't seem to find the solution. How do I do this? Here's the code for the Player (JugadorScript.cs):
using UnityEngine;
using System.Collections;
public class JugadorScript : MonoBehaviour
{
public float velocidad = -10f;
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void moverIzquierda()
{
transform.Translate(Vector2.right * velocidad * Time.deltaTime);
transform.eulerAngles = new Vector2(0, 0);
}
public void moverDerecha()
{
transform.Translate(Vector2.right * velocidad * Time.deltaTime);
transform.eulerAngles = new Vector2(0, 180);
}
}
The EnemySpawner.cs code, which works excellent:
using UnityEngine;
using System.Collections;
using System;
public class EnemySpawner : MonoBehaviour
{
public GameObject BlockPrefab;
float maxSpawnRateInSeconds = 2.5f;
void Start()
{
Invoke("SpawnEnemy", maxSpawnRateInSeconds);
InvokeRepeating("IncreaseSpawnRate", 0f, 30f);
}
// Update is called once per frame
void Update()
{
}
void SpawnEnemy()
{
Vector2 min = Camera.main.ViewportToWorldPoint(new Vector2(0, 0));
Vector2 max = Camera.main.ViewportToWorldPoint(new Vector2(1, 1));
GameObject anEnemy = (GameObject)Instantiate(BlockPrefab);
anEnemy.transform.position = new Vector2(UnityEngine.Random.Range(min.x, max.x), max.y);
ScheduleNextEnemySpawn();
}
void ScheduleNextEnemySpawn()
{
float spawnInNSeconds;
if (maxSpawnRateInSeconds > 1f)
{
spawnInNSeconds = UnityEngine.Random.Range(1f, maxSpawnRateInSeconds);
}
else
spawnInNSeconds = 1f;
Invoke("SpawnEnemy", spawnInNSeconds);
}
void IncreaseSpawnRate()
{
if (maxSpawnRateInSeconds > 1f)
maxSpawnRateInSeconds--;
if (maxSpawnRateInSeconds == 1f)
CancelInvoke("IncreaseSpawnRate");
}
}
And the BlockScript.cs, which is my enemy script:
using UnityEngine;
using System.Collections;
public class BlockScript : MonoBehaviour
{
private GameObject wayPoint;
private Vector3 wayPointPos;
private Rigidbody2D rigidBody2D;
public bool inGround = true;
private float jumpForce = 400f;
private float speed = 6.0f;
void Start()
{
wayPoint = GameObject.Find("wayPoint");
}
private void awake()
{
rigidBody2D = GetComponent<Rigidbody2D>();
}
void Update()
{
if (inGround)
{
inGround = false;
rigidBody2D.AddForce(new Vector2(0f, jumpForce));
}
wayPointPos = new Vector3(wayPoint.transform.position.x, transform.position.y,
wayPoint.transform.position.z);
transform.position = Vector3.MoveTowards(transform.position,
wayPointPos, speed * Time.deltaTime);
Vector2 min = Camera.main.ViewportToWorldPoint(new Vector2(0, 0));
if (transform.position.y < min.y)
{
Destroy(gameObject);
}
}
}
As you can see in the doc, the function you are looking for is OnCollisionEnter.
Check this tutorial:
https://unity3d.com/es/learn/tutorials/topics/physics/detecting-collisions-oncollisionenter
The [SyncVar] attribute is not working for me in my game. I have made sure that:
I changed the variable with a command function
I correctly added the syncvar attribute and the hook
The client can update the variables on the server, but the server is not updating the variable on the client
Here are my scripts:
Player Shooting Script:
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class PlayerShoot : NetworkBehaviour {
public GameObject shootPosition;
public float shootRange = 100;
public float shootRate = 0.2f;
float nextCheck;
public int damage = 10;
// Use this for initialization
void Start () {
}
void DetectShooting(){
if (Time.time > nextCheck && Input.GetMouseButton(0)) {
nextCheck = Time.time + shootRate;
CmdShoot ();
}
}
[Command]
void CmdShoot(){
RaycastHit hit;
Ray bulletDirection = new Ray (shootPosition.transform.position, transform.forward * shootRange);
Debug.DrawRay (shootPosition.transform.position, transform.forward * shootRange, Color.blue, 10.0f);
if (Physics.Raycast (bulletDirection, out hit, 100)) {
print (hit.transform.name);
if (hit.transform.CompareTag ("Player")) {
hit.transform.GetComponent<PlayerHealth> ().DeductHealth (damage);
}
}
}
// Update is called once per frame
void Update () {
print (isLocalPlayer);
if (isLocalPlayer)
DetectShooting ();
}
}
Player Health Script:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.Networking;
public class PlayerHealth : NetworkBehaviour {
public static int maxHealth = 100;
[SyncVar (hook ="UpdateUI")]
public int currentHealth = maxHealth;
public Slider healthBar;
void UpdateUI(int hp){
healthBar.value = currentHealth;
}
public void DeductHealth(int damage){
if (isServer)
currentHealth -= damage;
}
// Use this for initialization
void Start () {
//InvokeRepeating ("DeductHealth", 0, 2);
SetInitialReferences ();
}
void SetInitialReferences(){
}
// Update is called once per frame
void Update () {
}
}
Here are some Screen Shots:
Since you are hooking the SyncVar with function, you need to pass the variable manually (and do other stuff you wish to do with the new value like checking if hp <= 0).
void UpdateUI(int hp){
currentHealth = hp;
healthBar.value = currentHealth;
}