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.
Related
So the game knows what object it hit right up until the Interact() function is called in the Interactable script. I've used Debugs to try and find where the issue is and it seems to be that function, or rather in that script.
I want to make the game read which gameObject it hit and then put the "Item" it has assigned to that object to then add to the Inventory and delete the object, and it does that, except it adds the last created gameObject specifically. If I swap the "Items" in the gameObjects it will still start adding and deleting objects from the last created one.
I've attached all the scripts that are involved in this if that can help, but from what I can tell it's a problem with the Interactable script.
My best guess would be to somehow make the Interactable script think it's not the last created object, but I couldn't find info on how I could do that.
I'm sorry for this question with a huge amount of code, I hope it's not too much for a question
mouseLook:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class mouseLook : MonoBehaviour
{
public bool hasInteracted = false;
public bool wasFpressed = false;
public float mouseSensitivity = 100f;
public Transform playerBody;
float xRotation = 0f;
public float radius = 4f;
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
void Update()
{
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
playerBody.Rotate(Vector3.up * mouseX);
if (Input.GetKeyDown(KeyCode.F))
{
wasFpressed = true;
RaycastHit hit;
if (Physics.Raycast(Camera.main.transform.position, Camera.main.transform.forward, out hit, radius))
{
Interactable interactable = hit.collider.GetComponent<Interactable>();
Debug.Log(interactable);
if (interactable != null)
{
hasInteracted = true;
}
}
else
{
Debug.Log("Nothing");
}
}
}
}
Interactable:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using System;
public class Interactable : MonoBehaviour
{
public LayerMask interactableLayerMask;
public Item item;
public mouseLook inter;
public virtual void Interact()
{
//at this point the console tells me the gameObject is the last created object
Debug.Log(gameObject);
}
void Update()
{
if (inter.hasInteracted && inter.wasFpressed)
{
inter.hasInteracted = false;
inter.wasFpressed = false;
Interact();
}
}
}
ItemPickup:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemPickup : Interactable
{
public override void Interact()
{
base.Interact();
Debug.Log("Interacted with " + item.name);
PickUp();
}
void PickUp()
{
Debug.Log("Picking up " + item.name);
bool wasPickedUp = Inventory.instance.Add(item);
if (wasPickedUp)
{
Destroy(gameObject);
Debug.Log("Destroyed Item");
}
}
}
Inventory:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Inventory : MonoBehaviour
{
#region Singleton
public static Inventory instance;
void Awake()
{
if (instance != null)
{
Debug.LogWarning("More than one instance of Inventory found!");
return;
}
instance = this;
}
#endregion
public delegate void OnItemChanged();
public OnItemChanged onItemChangedCallback;
public int space = 20;
public List<Item> items = new List<Item>();
public bool Add (Item item)
{
if (!item.isDefaultItem)
{
if (items.Count >= space)
{
Debug.Log("Note enough space in inventory");
return false;
}
else
{
items.Add(item);
if (onItemChangedCallback != null)
onItemChangedCallback.Invoke();
}
}
return true;
}
public void Remove(Item item)
{
items.Remove(item);
if (onItemChangedCallback != null)
onItemChangedCallback.Invoke();
}
}
Item:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Item", menuName = "Inventory/Item")]
public class Item : ScriptableObject
{
new public string name = "New Item";
public Sprite icon = null;
public bool isDefaultItem = false;
}
What I'm trying to do is have my player stop moving so I can play animation through a trigger-event or just a custscene.
What I expect was for one of them to trigger the timer then play animation>player move.. like a cut-scene
Also there are no errors In any of them They just didn't stop player from moving or just stop the player when starting the game(or when I press play it just set forwardMovement to 0)
Here's the code I use:
public class Player_controls : MonoBehaviour
{
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class Player_controls : MonoBehaviour
{
public int forwardMovement = 1000;
public void Update()
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
}
}
Things that I tried:
public void ForwardMovement()
{
forwardMovement = 0;
Invoke("Action", 2f);
}
public void Action ()
{
forwardMovement = 1000 ;
}
Which only works for ForwardMovement(); method nothing else
I tried these two things also:
Public static class MonoExtensions
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public float Delayer = 10f;
public static class MonoExtensions
{
public static void Timed_delay(this MonoBehaviour mono,Action function, float Delayer)
{
mono.StartCoroutine(Timed_delayRoutine(function,Delayer));
}
static IEnumerator Timed_delayRoutine(Action function, float Delayer)
{
yield return new WaitForSeconds(Delayer);
function();
}
public class `Player_Controls`: MonoBehaviour
{
public void PM ()
{
forwardMovement = 0;
}
void OnTriggerEnter(Collider other)
{
if (CompareTag("Power_up"))
{
this.Timed_delay(PM, Delayer);
}
}
}
Which just stop the player from moving an nothing else.
What I also tried was:
public class Player_Controls : MonoBehaviour
{
void Start()
{
StartCoroutine(ForwardMovement());
}
IEnumerator ForwardMovement()
{
forwardMovement = 0;
yield return new waitforseconds(Delayer);
forwardMovement = 1050;
}
void OnTriggerEnter(collider other)
{
if (CompareTag("Power_up"))
{
ForwardMovement();
}
}
}
Which did not work as in(it works but the timer part does nothing, so the player can't move when started the game )
Different way I tried
public class Player_Controls : MonoBehaviour
{
OnTriggerEnter(collider other)
{
Startcroutine(ForwardMovement ));
}
}
it didn't work but no Errors.
I tried this one by jazzhar:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class Player_controls : MonoBehaviour
{
// Drag the player in the inspector here;
public Rigidbody rb;
// Youre speed variable for movement.
public float Speed = 5;
// Youre speed variable for movement.
public int forwardMovement = 1000;
// Set this "stopmoving" bool to true to prevent movement.
public bool stopMoving = false;
// Create and select the right layer in the inspector.
public LayerMask WichObjectStopsMovement;
public void Update()
{
// if stopMoving = true than Dont Add force.
if (stopMoving == false)
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
}
private void OnCollisionEnter(Collision collision)
{
// if you're player touches a object and that object's layer
// is the same as "WichObjectStopsMovement" than disable Movement.
if (collision.collider.gameObject.layer == WichObjectStopsMovement)
{
stopMoving = false;
}
}
}
It sorta works in a way if you set if
if (stopMoving == true)
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
and
if (collision.collider.gameObject.layer == WichObjectStopsMovement)
{
stopMoving = true;
}
then the player would be able to move but it will not trigger if hit the cube
it didn't work either but no Errors.
And some other timers I did but forgotten....
_________________________________________________________________March/6/21
public float Delayer = 10.0f;
I think found solution by doing this
private void OnTriggerEnter(Collider other)
{
if (CompareTag("Power_up"))
{
Delayer -= Time.deltaTime; <- this part giving me the error
if (Delayer => 0)
{
forwardMovement = 0;
}
}
}
but their one problem it giving me the this error Cannot convert lambda expression to type 'bool' because it is not a delegate type [Assembly-CSharp]csharp(CS1660) I don't know much about this even searching about doesn't help either
__________________________________________________________________March 28/21
this script is under player controls
this one works I made sure by doing Debug.Log("test");
void OnTriggerExit(Collider collision)
{
if (collision.gameObject.CompareTag("Power_up"))
{
forwardMovement = 0;
}
if (forwardMovement <= 0)
{
Debug.Log("test");
}
This might be a solution to you're problem, Fire-Source!:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class Player_controls : MonoBehaviour
{
// Drag the player in the inspector here;
public Rigidbody rb;
// Youre speed variable for movement.
public float Speed = 5;
// Youre speed variable for movement.
public int forwardMovement = 1000;
// Set this "stopmoving" bool to true to prevent movement.
public bool stopMoving = false;
// Create and select the right layer in the inspector.
public LayerMask WichObjectStopsMovement;
public void Update()
{
// if stopMoving = true than Dont Add force.
if (stopMoving == false)
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
}
private void OnCollisionEnter(Collision collision)
{
// if youre player touches a object and that object's layer
// is the same as "WichObjectStopsMovement" than disable Movement.
if (collision.collider.gameObject.layer == WichObjectStopsMovement)
{
stopMoving = false;
}
}
}
This code uses a LayerMask, to create 1 click on any object and in the inspector go:
Click on Layer:
Add Layer:
Write in User Layer 6, StopMovement (or anything else).
Than in the object that should stop player movement:
Click on layer:
Than select the Layer that says StopMovement.
And in you're player's script drag the object into the rb variable.
and in "WichObjectStopsMovement" assign the StopMovement layer.
This should take care of everything is that ok?
so I'm trying to get this code to run, but its asking something about static which I don't really get. any help would make me happy :).
basically I wanted to make it so every time you jump your jump height would be lower.
and that error at the top came out which I honestly (even after searching a bit) have no idea what it means.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class zoom : MonoBehaviour
{
// Start is called before the first frame update
public float zoomSpeed = 5f;
public float upZoom = 20f;
public bool flor = false;
public float jumpamount = 5f;
void Start()
{
}
// Update is called once per frame
void Update()
{
Jump();
Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, 0f);
transform.position += movement * Time.deltaTime * zoomSpeed;
}
void Jump()
{
if (Input.GetButtonDown("Jump") && flor == true);
{
upZoom = (upZoom - jumpamount);
gameObject.GetComponent<Rigidbody2D>().AddForce(new Vector2(0f, upZoom), ForceMode2D.Impulse);
}
}
}
other one
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class onflor : MonoBehaviour
{
GameObject mouseplayerreal;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
mouseplayerreal = gameObject.transform.gameObject;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.tag == "Guroundo")
{
zoom.upZoom = 20f;
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.collider.tag == "Guroundo")
{
}
}
}
So i want to make a button change the variable in one script. Then i want another script to get that variable from the first script. How do i do this.
I have tried somethings but im not sure if i did them correctly
When i try it like in the code below. Then it gives me the message:
'The type or namespace name 'jumpscript' could not be found (are you missing a using directive or an assembly reference?)'
Jump.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Jump : MonoBehaviour
{
public bool jump = false;
// Start is called before the first frame update
public void JumpOnClick()
{
jump = true;
}
// Update is called once per frame
void Update()
{
}
}
PlayerMovement.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController2D controller;
public Joystick joystick;
public jumpscript Jump;
public float runSpeed = 40f;
float horizontalMove = 0f;
// Update is called once per frame
void Update()
{
if (joystick.Horizontal >= .2f)
{
horizontalMove = runSpeed;
} else if (joystick.Horizontal <= -.2f)
{
horizontalMove = -runSpeed;
} else
{
horizontalMove = 0f;
}
}
void FixedUpdate()
{
controller.Move(horizontalMove * Time.fixedDeltaTime, false, Jump.jump);
Jump.jump = false;
}
}
EDIT: I got the character to jump but the character is always jumping.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController2D controller;
public Joystick joystick;
public Jump jumpScript;
public float runSpeed = 40f;
float horizontalMove = 0f;
bool Jump = false;
// Update is called once per frame
void Update()
{
if (jumpScript.jump == true)
{
Jump = true;
}
if (joystick.Horizontal >= .2f)
{
horizontalMove = runSpeed;
} else if (joystick.Horizontal <= -.2f)
{
horizontalMove = -runSpeed;
} else
{
horizontalMove = 0f;
}
}
void FixedUpdate()
{
controller.Move(horizontalMove * Time.fixedDeltaTime, false, Jump);
Jump = false;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Jump : MonoBehaviour
{
public bool jump = false;
// Start is called before the first frame update
public void JumpOnClick()
{
jump = true;
jump = false;
}
// Update is called once per frame
void Update()
{
}
}
Please help me.
Okay, so first thing to note, I am assuming both of these scripts are on the one gameobject.
You have to create a local variable out of the jump script. You can accomplish it like this:
private Jump jumpScript;
// Start is called before the first frame update
void Start()
{
jump = this.GetComponent<Jump>();
jump.JumpOnClick();
}
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;
}