I got an error from Unity while I was busy executing a command for the server. The error is:
Command function CmdSpawnPlayer called on server.
UnityEngine.Debug:LogError(Object)
NetworkHandler:CallCmdSpawnPlayer(Boolean)
NetworkHandler:OnEnable() (at Assets/Scripts/Managers/NetworkHandler.cs:69)
UnityEngine.Networking.NetworkIdentity:UNetStaticUpdate()
Here is the code I use:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
public class NetworkHandler : NetworkBehaviour
{
public Player NetworkPlayer
{
get;
private set;
}
public bool HasInternet
{
get
{
return Network.HavePublicAddress();
}
}
public bool IsConnectedToServer
{
get
{
return networkManager.isNetworkActive;
}
}
[SerializeField]
private NetworkManager networkManager;
[SerializeField]
private GameObject playerPrefab, spectatorPrefab;
public void StartClient()
{
networkManager.StartClient();
}
public void StartServer()
{
networkManager.StartServer();
}
[Command]
private void CmdSpawnPlayer(bool isSpectator)
{
SpawnPlayer(isSpectator);
}
private void SpawnPlayer(bool isSpectator)
{
if (isSpectator)
{
NetworkServer.SpawnWithClientAuthority(Instantiate(spectatorPrefab), connectionToClient);
}
else
{
NetworkServer.SpawnWithClientAuthority(Instantiate(playerPrefab), connectionToClient);
}
}
private void OnEnable()
{
if (IsConnectedToServer)
{
CmdSpawnPlayer(true);
Game.CameraHandler.InstantiateMode();
}
}
}
The Unity version is use is 5.3.4f1.
Okay, nevermind. It seems that I have called CmdSpawnPlayer(true); from the server instead of the LocalClient.
Related
So i made a starter game from brackeys and i get 3 errors please help me
Script:GameManager
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
public bool gameHasEnded = false;
public float restartDelay = 1f;
public void CompleteLevel ()
{
Debug.Log("LEVEL COMPLETE");
}
public void EndGame ()
{
if (gameHasEnded == false)
{
gameHasEnded = true;
Debug.Log("GAME OVER");
Invoke("Restart", restartDelay);
}
}
void Restart ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
script:EndTriger
using UnityEngine;
public class EndTriger : MonoBehaviour
public GameManager gameManager;
{
void OnTriggerEnter()
{
gameManager.CompleteLevel();
}
}
EndTriger:
using UnityEngine;
public class EndTriger : MonoBehaviour
{
public GameManager gameManager;
void OnTriggerEnter()
{
gameManager.CompleteLevel();
}
}
I'm using state pattern for my unity game. I have three states; HappyState, SurprisedState and SadState. HappyState is default state. I want the character to jump and enter surprised state by clicking left-mouse. Entering surprised state, a few jobs need to be done which I defined as a void to be subscribed to an event, But it doesn't work!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
public class CapsuleScript : MonoBehaviour
{
public event Action SliderAction;
public Slider slider;
public Text stateText;
public GameObject hands;
public Rigidbody rb;
public CapsuleBasicStates currentstate;
public readonly HappyState happyState = new HappyState();
public readonly SadState sadState = new SadState();
public readonly SurprisedState surprisedState = new SurprisedState();
public SpriteRenderer renderer;
public Sprite happysprite, sadsprite, surprisedsprite;
// Start is called before the first frame update
void Start()
{
slider.value = 0;
renderer = GetComponentInChildren<SpriteRenderer>();
rb = GetComponent<Rigidbody>();
TransitionToState(happyState);
}
public void OnCollisionEnter(Collision other) {
currentstate.OnCollisionEnter(this);
}
// Update is called once per frame
void Update()
{
currentstate.Update(this);
}
public void SetSprite(Sprite sprite)
{
renderer.sprite = sprite;
}
public void TransitionToState(CapsuleBasicStates state)
{
currentstate = state;
currentstate.EnterState(this);
}
public IEnumerator SliderHandler()
{
yield return new WaitForSeconds(1f);
slider.value +=1;
StartCoroutine(SliderHandler());
}
public void IEHandler()
{
StartCoroutine(SliderHandler());
}
}
Here is SurprisedState script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SurprisedState : CapsuleBasicStates
{
public override void EnterState(CapsuleScript player)
{
player.SetSprite(player.surprisedsprite);
player.stateText.text = player.surprisedState.ToString();
player.slider.gameObject.SetActive(true);
player.SliderAction += player.IEHandler;
}
public override void OnCollisionEnter(CapsuleScript player)
{
//player.TransitionToState(player.happyState);
}
public override void Update(CapsuleScript player)
{
if(player.slider.value ==20)
{
player.SliderAction -= player.IEHandler;
player.TransitionToState(player.happyState);
}
}
}
HappyState script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HappyState : CapsuleBasicStates
{
public override void EnterState(CapsuleScript player)
{
player.SetSprite(player.happysprite);
player.stateText.text = player.happyState.ToString();
player.hands.SetActive(false);
}
public override void OnCollisionEnter(CapsuleScript player)
{
}
public override void Update(CapsuleScript player)
{
if(Input.GetButton("Fire1"))
{
player.rb.AddForce(Vector3.up * 150f);
player.TransitionToState(player.surprisedState);
}
if(Input.GetButton("Fire2"))
{
player.rb.AddForce(Vector3.up *250f);
player.TransitionToState(player.sadState);
}
}
}
Few points before I post my solution:
Try to post all scripts related to the question you are asking.
Comment your code or try to explain what each part of your script is doing.
BaseSate.cs
[System.Serializable]
public abstract class BaseState
{
public enum PlayerStates { HappyState = 0, SurprisedState = 1 }
public abstract PlayerStates PlayerState { get; }
public abstract void EnterState(PlayerScript playerScript);
public abstract void UpdateState();
public abstract void ExitState();
}
HappySate.cs
using UnityEngine;
[System.Serializable]
public class HappyState : BaseState
{
public override PlayerStates PlayerState => PlayerStates.HappyState;
private PlayerScript _playerScript;
public override void EnterState(PlayerScript playerScript)
{
_playerScript = playerScript;
Debug.Log($"Entered {PlayerState}");
}
public override void UpdateState()
{
if (Input.GetButtonDown("Fire1"))
{
_playerScript.ChangeState(new SurprisedState());
}
}
public override void ExitState()
{
Debug.Log($"Exited {PlayerState}");
}
}
SurprisedState.cs
using UnityEngine;
[System.Serializable]
public class SurprisedState : BaseState
{
public override PlayerStates PlayerState => PlayerStates.SurprisedState;
private PlayerScript _playerScript;
public override void EnterState(PlayerScript playerScript)
{
_playerScript = playerScript;
// subscribe to sliderAction on enter
playerScript.playerSliderAction += OnSliderChange;
Debug.Log($"Entered {PlayerState}");
}
private void OnSliderChange(float sliderValue)
{
// use Mathf.Approximately instead of == when comparing
// floating numbers.
if (Mathf.Approximately(sliderValue, 20f))
{
_playerScript.ChangeState(new HappyState());
}
}
public override void UpdateState() { }
public override void ExitState()
{
// unSubscribe to sliderAction on exit
_playerScript.playerSliderAction -= OnSliderChange;
Debug.Log($"Exited {PlayerState}");
}
}
PlayerScript.cs
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
public class PlayerScript : MonoBehaviour
{
[SerializeField]
private SpriteRenderer playerRenderer;
[SerializeField]
private Sprite[] playerStateSprites;
[SerializeField]
private Slider playerSlider;
public UnityAction<float> playerSliderAction;
private BaseState _currentState;
private void Awake()
{
Initialize();
}
private void Update()
{
_currentState.UpdateState();
}
private void Initialize()
{
ChangeState(new HappyState());
// use slider onValueChanged instead of checking slider
// value every frame.
// invoke unity action when the value has been changed.
playerSlider.onValueChanged.AddListener(sliderValue =>
{
playerSliderAction?.Invoke(sliderValue);
});
}
public void ChangeState(BaseState newState)
{
// change state only when it is different
// from previous state.
if (_currentState == newState)
{
return;
}
_currentState?.ExitState();
_currentState = newState;
_currentState.EnterState(this);
playerRenderer.sprite = playerStateSprites[(int)newState.PlayerState];
Debug.Log($"Current State : {_currentState.PlayerState}");
}
}
PlayerScript inspector view
Execution Overview gif:
https://gfycat.com/grimflowerycollardlizard
I have implemented the state pattern for my game in Unity.
Thus I have a main class (BattleSystem) which starts by calling different states.
One of those states is the AttackState. The AttackState has an attackButton which is an UI Button (using UnityEngine.UI).
My State class looks like this:
public abstract class State : MonoBehaviour
{
protected BattleSystem battleSystem;
public abstract void Tick();
public virtual void OnStateEnter() { }
public virtual void OnStateExit() { }
public State(BattleSystem battleSystem) {
this.battleSystem = battleSystem;
}
}
My StateMachine class looks like this:
public abstract class StateMachine : MonoBehaviour
{
protected State state;
public void SetState(State state) {
this.state = state;
state.OnStateEnter();
}
}
The Button is in the BattleSystem class like this:
public class BattleSystem : StateMachine
{
public Button attackButton;
// Start is called before the first frame update
void Start()
{
SetState(new AttackState(this));
}
I dragged the AttackButton object onto my attackButton field in the inspector in the Unity editor.
My AttackState.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class AttackState : State
{
public AttackState(BattleSystem battleSystem) : base(battleSystem)
{
}
public override void Tick()
{
}
public override void OnStateEnter()
{
Debug.Log("AttackState");
battleSystem.attackButton.onClick.AddListener(delegate () { this.Attack(); });
Debug.Log(battleSystem.attackButton.gameObject.name);
}
public void Attack() {
Debug.Log("Attacking");
foreach (Transform child in battleSystem.cardDropZone.transform)
{
Card card = (Card)child.GetComponent("Card");
// inflict damage to opponent equal to attack of cards
if (battleSystem.canDamageBeInflicted(card))
{
battleSystem.inflictDamage(card);
// adjust crystalCount
TurnUtilities.crystalCount -= card.crystalCost;
// Move card to graveyard after it has been used
battleSystem.sendToGraveyard(child);
battleSystem.attackButton.GetComponentInChildren<Text>().text = "End Turn";
}
else
{
Debug.Log("not enough crystals");
}
}
if (PlayerIsDead())
{
battleSystem.isPlayerDead = true;
battleSystem.SetState(new GameEndingState(battleSystem));
}
if (EnemyIsDead())
{
battleSystem.isEnemyDead = true;
battleSystem.SetState(new GameEndingState(battleSystem));
}
}
bool PlayerIsDead()
{
if (battleSystem.playerHealthbar.value <= 0)
{
return true;
}
return false;
}
bool EnemyIsDead()
{
if (battleSystem.enemyHealthbar.value <= 0)
{
return true;
}
return false;
}
}
The funny thing is that the Debug.Log(battleSystem.attackButton.gameObject.name); works and gives me the name of the GameObject. The event is not being registered though. What did I miss?
Picture of my Scene:
EDIT: I found out that this code works:
btn.onClick.AddListener(() => Debug.Log("Test"));
Putting the method inside does not work? What is happening here :D
Something really odd happens when I'm trying to load a scene.
The code that generates an error (I guess):
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class playSc : MonoBehaviour {
public string levelToLoad;
public Animator menumusic;
public GameObject background;
public GameObject text;
public GameObject progressSlider;
public Text progressText;
public Slider progressBar;
private int loadProgress = 0;
public void close()
{
Application.Quit();
}
public void play()
{
menumusic.SetBool("FadeOUT", true);
GameObject.Find("Clock").SetActive(false);
progressText.text = "Think about the Universe to continue.\nThinking progress:";
StartCoroutine(DisplayLoadingScreen("Game"));
}
public void credits()
{
menumusic.SetBool("FadeOUT", true);
GameObject.Find("Clock").SetActive(false);
progressText.text = "Think about your behaviour.\nThinking progress:";
StartCoroutine(DisplayLoadingScreen("Credits"));
}
IEnumerator DisplayLoadingScreen(string level)
{
background.SetActive(true);
text.SetActive(true);
progressSlider.SetActive(true);
AsyncOperation async = SceneManager.LoadSceneAsync(level);
while (!async.isDone)
{
loadProgress = (int)(async.progress * 100);
progressBar.value = loadProgress;
yield return null;
}
}
}
I tried to use Application.LoadLevel() and it still is not working. It was working with this code but at one moment it stopped.
I need to call updateGold() in ShowMoney class but failed.
If success,it should show money.gold in console, but don't show anything.
And golText.text don't update.
Even I change to Debug.Log("OK") in updateGold(),don't show anything in console.
But when I call updateGold() in Money class, it success. What the difference?
=========================================================
//Prop.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class Prop : MonoBehaviour,IPointerClickHandler
{
public int goldPrice;
public int diamondPrice;
public int propID;
public GameObject goldError;
public GameObject diamondError;
public GameObject purchasePanel;
//check if purchased when back to this Level
void Awake()
{
if(Bag.propIsPurchased[propID]==true)
{
alreadySold();
}
}
//show purchase panel and add delegate
public void OnPointerClick (PointerEventData eventData)
{
purchasePanel.SetActive(true);
ConfirmPurchase.ensureOperation += this.purchase;
CancelPurchase.cancelOperation += this.cancel;
}
public void purchase()
{
if (goldPrice>0)
{
if(goldPrice > Money.gold)
{
goldError.SetActive(true);
}
else
{
Money.payGold(goldPrice);
ShowMoney.updateGold();//problem here
Bag.addProp(propID);
alreadySold();
}
}
//...
}
//...
//ShowMoney.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class ShowMoney : MonoBehaviour
{
public GameObject goldText;
public GameObject diamondText;
public static Text golText;
public static Text diaText;
void Awake()
{
golText = goldText.GetComponent<Text>();
diaText = diamondText.GetComponent<Text>();
updateGold();
updateDiamond();
}
public static void updateGold()
{
Debug.Log(Money.gold);
golText.text = Money.gold.ToString();
}
public static void updateDiamond()
{
diaText.text = Money.diamond.ToString();
}
}
//Money.cs
using UnityEngine;
using System.Collections;
public class Money: MonoBehaviour
{
public static int gold = 100;
public static int diamond = 20;
public static Money instance;
void Awake()
{
instance = this;
}
public static void earnGold(int gol)
{
gold += gol;
}
public static void earnDiamond(int dia)
{
diamond += dia;
}
public static void payGold(int gol)
{
gold -= gol;
//ShowMoney.updateGold();//can work here
}
public static void payDiamond(int dia)
{
diamond -= dia;
}
}
Define your method Before Void and still Problem not solved then Make Protected Method that only accessible by its next method .
public static void updateGold()
{
Debug.Log(Money.gold);
golText.text = Money.gold.ToString();
}
public static void updateDiamond()
{
diaText.text = Money.diamond.ToString();
}
public void Awake()
{
golText = goldText.GetComponent<Text>();
diaText = diamondText.GetComponent<Text>();
updateGold();
updateDiamond();
}