I am a beginner using C# and trying to create a touch controller, but when it compiles it gives following error:
Jostick.inputVector is inaccessible due to its protection level.
Following is the script:
using UnityEngine;
using UnityStandardAssets.Characters.FirstPerson;
public class CalleAll : MonoBehaviour
{
public FixedJoystick MoveJoystick;
public FixedTouchField TouchField;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
var fps = GetComponent<RigidbodyFirstPersonController>();
fps.RunAxis = MoveJoystick.inputVector;
fps.mouseLook.LookAxis=TouchField.TouchDist;
}
}
And this is the script file.
using UnityEngine;
using UnityEngine.EventSystems;
public class FixedJoystick : Joystick
{
public Vector2 joystickPosition = Vector2.zero;
private Camera cam = new Camera();
void Start()
{
joystickPosition = RectTransformUtility.WorldToScreenPoint(cam, background.position);
}
public override void OnDrag(PointerEventData eventData)
{
Vector2 direction = eventData.position - joystickPosition;
///here it is
inputVector = (direction.magnitude > background.sizeDelta.x / 2f) ? direction.normalized : direction / (background.sizeDelta.x / 2f);
ClampJoystick();
handle.anchoredPosition = (inputVector * background.sizeDelta.x / 2f) * handleLimit;
}
public override void OnPointerDown(PointerEventData eventData)
{
OnDrag(eventData);
}
public override void OnPointerUp(PointerEventData eventData)
{
inputVector = Vector2.zero;
handle.anchoredPosition = Vector2.zero;
}
}
The error is because the class Joystick has a protected member already named inputVector - you cannot use it from within types other than its subclasses (which is why FixedJoystick can use it, but not CalleAll, as CalleAll does not derive from Joystick).
You can make the data available to consumers by creating a readonly property that exposes the data:
class FixedJoystick : Joystick
{
public Vector2 InputVector
{
get { return this.inputVector; }
}
}
class CalleAll : MonoBehaviour
{
void Update()
{
var fps = GetComponent<RigidbodyFirstPersonController>();
fps.RunAxis = this.MoveJoystick.InputVector;
}
}
Related
I have class UnitComponent that contains references to every script of the unit. Every unit has scripts UnitUI and UnitStats. So I can access UnitUI methods from UnitStats using UnitComponent class (for example: unitComponent.unitUI.SetHealthUI()). Of course, every script has a reference to UnitComponent class as well to be able to use it. These three scripts have children (PlayerComponent, PlayerUI, PlayerStats). These classes have new methods, for example PlayerUI has SetManaUI() method. But I can't use SetManaUI() using PlayerComponent without creating new variable with PlayerUI class because UnitUI variable doesn't have this method. Is there any option to make new methods accessible through variable unitUI by changing class to PlayerUI or I have to create new PlayerUI variable and somehow get rid of unitUI.
I've tried to make virtual empty method SetManaUI() in UnitUI class and override it in PlayerUI class to make everything work, but it seems like a bad practise because UnitUI can become full of useless empty virtual methods.
Simplified version of scripts
Script that connects scripts together
using UnityEngine;
public class Collector : MonoBehaviour
{
public Stats stats;
public UI ui;
}
UI script
using UnityEngine;
public class UI : MonoBehaviour
{
Collector collector;
public void UIMethod()
{
Debug.Log("UI method");
}
}
Stats script
using UnityEngine;
public class Stats : MonoBehaviour
{
Collector collector;
public void StatsMethod()
{
Debug.Log("Stats method");
}
}
Child of collector script
public class ChildCollector : Collector
{
public string someNewData;
public string someNewData1;
public string someNewData2;
public void Start()
{
ui.ChildUIMethod(); //has to be executed and write "Child UI method"
stats.ChildStatsMethod(); //has to be executed and write "Child Stats method"
}
}
Child of UI script
using UnityEngine;
public class ChildUI : UI
{
ChildCollector childCollector;
public void ChildUIMethod()
{
Debug.Log("Child UI Method");
}
}
Child of Stats script
using UnityEngine;
public class ChildStats : Stats
{
ChildCollector childCollector;
public void ChildStatsMethod()
{
Debug.Log("Child Stats Method");
}
}
Full version of scripts
Unit Component script
using UnityEngine;
public class UnitComponent : MonoBehaviour
{
public Animator animator;
public UnitStats unitStats;
public UnitUI unitUI;
}
UnitStats script
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class UnitStats : MonoBehaviour
{
public UnitComponent unitComponent;
public float maxHealth;
public float health;
public List<GameObject> lootDrop;
protected virtual void Start()
{
if (health <= 0 || health > maxHealth)
health = maxHealth;
unitComponent.unitUI.SetHealthUI(health, maxHealth);
CheckDeath();
}
private void CreateDamagePopup(float takenDamage)
{
GameObject damagePopupCanvas = Instantiate(unitComponent.unitUI.damagePopupCanvasPref, transform.position, Quaternion.identity, transform);
damagePopupCanvas.GetComponentInChildren<Text>().text = takenDamage.ToString();
Vector3 randomPosOffset = new Vector3(Random.Range(-0.1f, 0.1f), Random.Range(-0.1f, 0.1f), 0f);
damagePopupCanvas.transform.position += randomPosOffset;
Destroy(damagePopupCanvas, 3f);
}
public float CalculateHealthPercentage()
{
return (health / maxHealth);
}
protected void CheckDeath()
{
if (health <= 0)
{
unitComponent.animator.SetTrigger("isDead");
DropLoot();
}
}
protected void CheckOverheal()
{
if (health > maxHealth)
{
health = maxHealth;
}
}
public void DealDamage(int damage)
{
unitComponent.unitUI.healthBar.SetActive(true);
health -= damage;
unitComponent.unitUI.SetHealthUI(health, maxHealth);
CheckDeath();
CreateDamagePopup(damage);
}
public void HealCharacter(int heal)
{
health += heal;
CheckOverheal();
unitComponent.unitUI.SetHealthUI(health, maxHealth);
}
public void DropLoot()
{
foreach (GameObject item in lootDrop)
Instantiate(item, transform.position, Quaternion.identity);
}
}
UnitUI script
using UnityEngine;
using UnityEngine.UI;
public class UnitUI : MonoBehaviour
{
public UnitComponent unitComponent;
public GameObject damagePopupCanvasPref;
public GameObject healthBar;
protected Slider healthBarSlider;
virtual public void Start()
{
healthBarSlider = healthBar.GetComponent<Slider>();
}
public virtual void SetHealthUI(float health, float maxHealth)
{
if (healthBarSlider)
healthBarSlider.value = health / maxHealth;
}
public virtual void SetCoinsUI(int coinAmount) { } //Necessary for PlayerUI script working
public virtual void SetManaUI(float mana, float maxMana) { } //Necessary for PlayerUI script working
}
PlayerComponent script
using UnityEngine;
public class PlayerComponent : UnitComponent
{
public PlayerMovement playerMovement;
public PlayerSlot playerSlot;
public Rigidbody2D rb;
}
PlayerStats script
using UnityEngine;
public class PlayerStats : UnitStats
{
protected int coins;
public float mana;
public float maxMana;
public float manaRegenPerSec;
protected override void Start()
{
UI = gameObject.GetComponent<PlayerUI>();
animator = gameObject.GetComponent<Animator>();
if (health <= 0 || health > maxHealth)
health = maxHealth;
UI.SetHealthUI(health, maxHealth);
UI.SetManaUI(mana, maxMana);
CheckDeath();
}
public void Update()
{
if (mana < maxMana)
{
mana += manaRegenPerSec * Time.deltaTime;
UI.SetManaUI(mana, maxMana);
}
}
private void Awake()
{
DontDestroyOnLoad(this);
}
public void AddCoins(int amount)
{
coins += amount;
UI.SetCoinsUI(amount);
}
}
PlayerUI script
using System;
using UnityEngine;
using UnityEngine.UI;
public class PlayerUI : UnitUI
{
[SerializeField] protected GameObject manaBar;
[SerializeField] protected Text manaValue;
[SerializeField] protected Text healthValue;
[SerializeField] protected Text coinValue;
protected Slider manaBarSlider;
public override void Start()
{
healthBarSlider = healthBar.GetComponent<Slider>();
manaBarSlider = manaBar.GetComponent<Slider>();
}
public override void SetHealthUI(float health, float maxHealth)
{
healthBarSlider.value = health / maxHealth;
healthValue.text = health.ToString() + "/" + maxHealth.ToString();
}
public override void SetManaUI(float mana, float maxMana)
{
manaBarSlider.value = mana / maxMana;
manaValue.text = Math.Round(mana).ToString() + "/" + Math.Round(maxMana).ToString();
}
public override void SetCoinsUI(int coinAmount)
{
coinValue.text = coinAmount.ToString();
}
}
So I'm trying to make a game with diferent unit types, each one with diferent movement speeds. I don't really know how to face this problem: At first I did a function on every unitType to define the speed but I don't think this is the most optimal way to do it. Now i was thinking about creating a MovementController class. This is what I did so far: First of all, I did a generic Unit Class -to keep it simple, I will just show the movement speed attribute- :
public class GenericUnit : MonoBehaviour
{
float movementSpeed;
public float mspeed
{
get { return movementSpeed; }
set { movementSpeed = value; }
}
}
after, I defined all atributes in a subClass depending of the unit type:
public class Archer : MonoBehaviour
{
GenericUnit archer;
void Start()
{
archer = new GenericUnit();
archer.mspeed = 3.0f;
}
}
This is the Movement controller I have right now:
public class Movement_Controller : MonoBehaviour
{
GenericUnit msUnit;
public float mspeed;
public bool movimentTrue;
void Start()
{
msunit = new GenericUnit();
mspeed = msUnit.mspeed;
movimentTrue = true;
}
void Update()
{
if (movimentTrue) {
Movement();
}
}
public void Movement(){
Vector3 moviment = new Vector3 (1.0f, 0.0f, 0.0f);
transform.position += Time.deltaTime * mspeed * moviment;
}
}
After all, this isn't working. Do you have any idea of whats the issue? I have been trying many other options that didn't make it. Do you think it's better to have this MovementController script or pasting the movement function on the Archer class? As you can see, im a novice on programming, so any suggestion would help a lot.
Thank you
What you are looking for is simple inheritence.
You describe the features you need in a base class and mark them (and the class) abstract. This enforces you to override it in all non abstract derived classed.
Base class:
public abstract class BaseUnit : MonoBehaviour
{
protected abstract float movementSpeed { get; } // force every deriving class to provide a movement speed
[SerializeField] private bool isMoving;
void Start()
{
isMoving = true;
}
void Update()
{
if (isMoving)
{
Movement();
}
}
public void Movement()
{
Vector3 direction = new Vector3(1.0f, 0.0f, 0.0f);
transform.position += Time.deltaTime * movementSpeed * direction;
}
}
Derived class Archer:
public class Archer : BaseUnit
{
protected override float movementSpeed => 3F;
}
Also note that you cannot create MonoBehaviours using the new keyword. You have to use AddComponent<T> to create or GetComponent<T> to retrieve them (see documentation).
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 trying to make my player have a constant speed forwards and i get this error when compiling.
public class Speed
{
public static int movespeed = 1;
public Vector3 userDirection = Vector3.right;
public Start()
{
}
public void Update()
{
transform.Translate(userDirection * movespeed * Time.deltaTime);
}
}
You forgot the return type of Start method :
public void Start()
By the way you also forgot inheritence to MonoBehavior (if you want to attach your script to a game object) ;-)
public class Speed : MonoBehaviour
public class Speed : MonoBehaviour
{
public static int movespeed = 1;
public Vector3 userDirection = Vector3.right;
public void Start()
{
}
public void Update()
{
transform.Translate(userDirection * movespeed * Time.deltaTime);
}
}
Your start method doesn't have a return type. Assign it one instead.
public void Start()
{
}
By the way this is really basic and shouldn't belong here.
This question already has answers here:
Unity: Null while making new class instance
(2 answers)
Closed 5 years ago.
The first script is attached to a empty GameObject.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class SpinableObject
{
public Transform t;
public float rotationSpeed;
public float minSpeed;
public float maxSpeed;
public float speedRate;
public bool slowDown;
}
public class SpinObject : MonoBehaviour
{
public SpinableObject[] objectsToRotate;
private Rotate _rotate;
private int index = 0;
// Use this for initialization
void Start()
{
_rotate = new Rotate>();
}
// Update is called once per frame
void Update()
{
var _objecttorotate = objectsToRotate[index];
_rotate.rotationSpeed = _objecttorotate.rotationSpeed;
_rotate.minSpeed = _objecttorotate.minSpeed;
_rotate.maxSpeed = _objecttorotate.maxSpeed;
_rotate.speedRate = _objecttorotate.speedRate;
_rotate.slowDown = _objecttorotate.slowDown;
}
}
The second script is attached to the GameObject/s i want to feed with information. So this script is attached to each GameObject separate.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotate : MonoBehaviour
{
public float rotationSpeed;
public float minSpeed;
public float maxSpeed;
public float speedRate;
public bool slowDown;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
RotateObject();
}
public void RotateObject()
{
if (rotationSpeed > maxSpeed)
slowDown = true;
else if (rotationSpeed < minSpeed)
slowDown = false;
rotationSpeed = (slowDown) ? rotationSpeed - 0.1f : rotationSpeed + 0.1f;
transform.Rotate(Vector3.forward, Time.deltaTime * rotationSpeed);
}
}
Not sure if this is a good way to what i want to do ?
Second problem is that the variable _rotate in the first script is all the time null:
I'm doing:
_rotate = new Rotate>();
But still here it's null:
_rotate.rotationSpeed = _objecttorotate.rotationSpeed;
I don't think you understand how Unity works.
First, _rotate = new Rotate>(); is not valid C# and will throw an error.
Second, in your case Rotate is a MonoBehaviour which is not attached to a GameObject. I think that whatever you tried to accomplish is maybe a step to far. You can' synchronize the Update-call of a deattached Component (of which I don't even know if it gets its Update-method called) with another object at all. In short: Your code seems nonsense to me.
I'd suggest, you move your RotateObject method into the SpinableObject and call it from SpinObject, instead of shoving stuff into _rotate. This should work.
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class SpinableObject
{
public Transform t;
public float rotationSpeed;
public float minSpeed;
public float maxSpeed;
public float speedRate;
public bool slowDown;
public void RotateObject()
{
if (rotationSpeed > maxSpeed)
slowDown = true;
else if (rotationSpeed < minSpeed)
slowDown = false;
rotationSpeed = (slowDown) ? rotationSpeed - 0.1f : rotationSpeed + 0.1f;
t.Rotate(Vector3.forward, Time.deltaTime * rotationSpeed);
}
}
public class SpinObject : MonoBehaviour
{
[SerializeField]
private SpinableObject[] objectsToRotate;
// Update is called once per frame
void Update()
{
foreach(var spinner in objectsToRotate)
spinner.RotateObject();
}
}