I am currently writing an application in C# with Unity, and I've hit a small stumbling block. I'm trying to change the value of a bool in the buyBusinessCourse() method of a class, but the value is unaffected. The initial value of the boolean is set to false, then I want the update method to run an if statement if it returns true.
public Text healthText;
public Text hungerText;
public Text moneyText;
public Text ageText;
public GameObject youDied;
public GameObject notEnoughMoney;
public GameObject mainScreenPanel;
public GameObject healthPanel;
public GameObject hungerPanel;
public GameObject storePanel;
public GameObject moneyPanel;
public GameObject bicycleImage;
public GameObject businessButton;
public GameObject boughtBusiness;
public int health;
public int hunger;
public int money;
public int age;
private bool business;
public void buyBusinessCourse()
{
if (money >= 3000)
{
money -= 3000;
moneyText.text = "Money: " + money;
Debug.Log("1");
businessButton.SetActive(false);
boughtBusiness.SetActive(true);
bool business = true;
Debug.Log(business);
return;
}
else
{
StartCoroutine(notEnoughMoneyCaroutine());
Debug.Log("2");
}
}
private void Start()
{
bool business = false;
Debug.Log(business);
}
//Update
private void Update()
{
if (health<0 | hunger<0 )
{
youDied.SetActive(true);
mainScreenPanel.SetActive(false);
healthPanel.SetActive(false);
hungerPanel.SetActive(false);
storePanel.SetActive(false);
moneyPanel.SetActive(false);
}
if (business == true)
{
Debug.Log("update"+business);
}
}
}
You don't need to respecify the type, just do business = true. However you are creating a local variable.
You've redefined business in if statement.
public void buyBusinessCourse()
{
if (money >= 3000)
{
...
bool business = true;
...
If you want to change the value of the business bool you need to write this.business=true or business=true.
public void buyBusinessCourse()
{
if (money >= 3000)
{
...
this.business = true;
...
Example
class Rect {
private int width;
private int height;
Rect(int width, int height) {
this.width=width; //Change the value of 'width member of Rect class'
this.height=height; //Change the value of height to given parameter.
}
changeWidthToTen() {
this.width=10;
}
}
Related
I have one rather ambiguous problem in my C# (Unity) code. It lies in the fact that my player disappears because of the prescribed lines about the spawnpoint. Because of them, my player simply disappears when I run the game
The lines where the problem is possible are 22, 109-112. Please help me with this problem. Thank you very much in advance
But I need spawnpoint for further work. Thank you very much in advance!
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
public static GameManager instance;
private void Awake()
{
if(GameManager.instance != null)
{
Destroy(gameObject);
Destroy(player.gameObject);
Destroy(floatingTextManager.gameObject);
Destroy(HUD);
Destroy(menu);
return;
}
instance = this;
SceneManager.sceneLoaded += LoadState;
SceneManager.sceneLoaded += OnSceneLoaded;
}
public List<Sprite> playerSprites;
public List<Sprite> weaponSprites;
public List<int> weaponPrices;
public List<int> xpTable;
public Player player;
public Weapon weapon;
public FloatingTextManager floatingTextManager;
public Animator misMenuAnim;
public RectTransform hitpointBar;
public GameObject HUD;
public GameObject menu;
public int pesos;
public int experience;
public void ShowText(string msg, int fontSize, Color color, Vector3 position, Vector3 motion, float duration)
{
floatingTextManager.Show(msg, fontSize, color, position, motion, duration);
}
public bool TryUpgradeWeapon()
{
if (weaponPrices.Count <= weapon.weaponLevel)
return false;
if(pesos >= weaponPrices[weapon.weaponLevel])
{
pesos -= weaponPrices[weapon.weaponLevel];
weapon.UpgradeWeapon();
return true;
}
return false;
}
public void OnHitpointChange()
{
float ratio = (float)player.hitpoint / (float)player.maxHitpoint;
hitpointBar.localScale = new Vector3(1, ratio, 1);
}
public int GetCurrentLevel()
{
int r = 0;
int add = 0;
while(experience >= add)
{
add += xpTable[r];
r++;
if (r == xpTable.Count)
return r;
}
return r;
}
public int GetXpToLevel(int level)
{
int r = 0;
int xp = 0;
while(r < level)
{
xp += xpTable[r];
r++;
}
return xp;
}
public void GrantXp(int xp)
{
int currLevel = GetCurrentLevel();
experience += xp;
if (currLevel < GetCurrentLevel())
OnLevelUp();
}
public void OnLevelUp()
{
player.OnLevelUp();
OnHitpointChange();
}
public void OnSceneLoaded(Scene s, LoadSceneMode mode)
{
player.transform.position = GameObject.Find("SpawnPoint").transform.position;
}
public void Respawn()
{
misMenuAnim.SetTrigger("Hide");
UnityEngine.SceneManagement.SceneManager.LoadScene("SampleScene");
player.Respawn();
}
public void SaveState()
{
string s = "";
s += "0" + "|";
s += pesos.ToString() + '|';
s += experience.ToString() + "|";
s += weapon.weaponLevel.ToString();
}
public void LoadState(Scene s, LoadSceneMode mode)
{
SceneManager.sceneLoaded += LoadState;
if (!PlayerPrefs.HasKey("SaveState"))
return;
string[] data = PlayerPrefs.GetString("SaveState").Split('|');
pesos = int.Parse(data[1]);
experience = int.Parse(data[2]);
player.SetLevel(GetCurrentLevel());
weapon.SetWeaponLevel(int.Parse(data[0]));
}
}
I have tried many ways over the course of a month, but none of them could solve the problem...
I have opened the unity(2021.3.7f1) first person module, and tried to add an attack animation to it. I have discovered that my code as soon as it takes 1 input(click), it keeps taking that input. The "isAttacking" variable, keeps being set to "true", even when the player is not clicking. The debug there is how I have figured out this problem.
I cannot for the life of me figure out why this is happening, please help.
Under StarterAssets
public class StarterAssetsInputs : MonoBehaviour
{
[Header("Character Input Values")]
public Vector2 move;
public Vector2 look;
public bool jump;
public bool sprint;
[Header("Movement Settings")]
public bool analogMovement;
[Header("Mouse Cursor Settings")]
public bool cursorLocked = true;
public bool cursorInputForLook = true;
// I added this in vv
public bool attack = false;
#if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED
public void OnMove(InputValue value)
{
MoveInput(value.Get<Vector2>());
}
public void OnLook(InputValue value)
{
if(cursorInputForLook)
{
LookInput(value.Get<Vector2>());
}
}
public void OnJump(InputValue value)
{
JumpInput(value.isPressed);
}
public void OnSprint(InputValue value)
{
SprintInput(value.isPressed);
}
// I added this in vv
public void OnAttack(InputValue value)
{
AttackInput(value.isPressed);
}
#endif
public void MoveInput(Vector2 newMoveDirection)
{
move = newMoveDirection;
}
public void LookInput(Vector2 newLookDirection)
{
look = newLookDirection;
}
public void JumpInput(bool newJumpState)
{
jump = newJumpState;
}
public void SprintInput(bool newSprintState)
{
sprint = newSprintState;
}
private void OnApplicationFocus(bool hasFocus)
{
SetCursorState(cursorLocked);
}
private void SetCursorState(bool newState)
{
Cursor.lockState = newState ? CursorLockMode.Locked : CursorLockMode.None;
}
// I added this in vv
private void AttackInput(bool newAttack)
{
attack = newAttack;
}
}
}
Under first-person controller
private void Attack()
{
if (_input.attack)
{
Debug.Log("Debug " + debugNR);
debugNR++;
WeaponController attackState = weapon.GetComponent<WeaponController>();
attackState.isAttacking = true;
}
}
Under weapon controller
public class WeaponController : MonoBehaviour
{
public Animator animator;
public bool isAttacking = false;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
animator.SetBool("Attack", isAttacking);
}
public void Attack()
{
isAttacking = false;
animator.SetBool("Attack", isAttacking);
}
}
Thanks in advance for the help
_input.attack must be set to false, as part of the attack function in the first person controller
The function was changed from:
private void Attack()
{
if (_input.attack)
{
Debug.Log("Debug " + debugNR);
debugNR++;
WeaponController attackState = weapon.GetComponent<WeaponController>();
attackState.isAttacking = true;
}
}
To:
private void Attack()
{
if (_input.attack)
{
Debug.Log("Debug " + debugNR);
debugNR++;
WeaponController attackState = weapon.GetComponent<WeaponController>();
attackState.isAttacking = true;
_input.attack = false;
}
}
recently I am making a game. There is a script named SizePositionForBullet.cs
the code of it was as:-
using UnityEngine;
using UnityEngine.UI;
public class SizePositionForBullet : MonoBehaviour
{
#region variables
//public variables
public Slider widthSetByUser;
public Slider heightSetByUser;
public Slider posXSetByUser;
public Slider posYSetByUser;
//private variables
public float width;
public float height;
public float posX;
public float posY;
#endregion
void Update()
{
#region Getting Player Prefs
posX = PlayerPrefs.GetFloat("posX", 323);
posY = PlayerPrefs.GetFloat("posY", 175);
width = PlayerPrefs.GetFloat("Width", 150);
height = PlayerPrefs.GetFloat("Height", 150);
#endregion
}
public void GetSliderValue(int pos)
{
if (pos == 1)
{
PlayerPrefs.SetFloat("posX", posXSetByUser.value);
}
if (pos == 2)
{
PlayerPrefs.SetFloat("posY", posYSetByUser.value);
}
if (pos == 3)
{
PlayerPrefs.SetFloat("Width", widthSetByUser.value);
}
if (pos == 4)
{
PlayerPrefs.SetFloat("Height", heightSetByUser.value);
}
}
}
So I need to use it's height , width and posX, posY variable in other class. So I added this code in class
public SizePositionForBullet _instance;
public static SizePositionForBullet Instance
{
get{
if(_instance == null)
{
_instance = GameObject.FindObjectOfType<BulletSizePosition>();
}
return _instance;
}
}
But when I use it in other class as it:-
float width = BulletSizePosition.Instance.width;
Unity saying: Null refrence Exception Object refrence not set to an instance of object at Assets/Scripts/BulletScript
How to solve it?
Your private _instance must be static too.
You are using the Singleton pattern. If this class reflect only player save (playerprefs) you don't have to make inheriting from MonoBehaviour.
public class MyPlayerSettings
{
public float Size;
...
private MyPlayerSettings()
{
LoadPreferences();
}
public void LoadPreferences()
{
// Get all your pref here
Size = PlayerPrefs.GetFloat("Size");
...
}
public static MyPlayerSettings Instance
{
get
{
if(instance == null)
{
instance = new MyPlayerSettings();
}
return instance;
}
}
private static MyPlayerSettings instance;
}
I have a quesition.
Is in this example did i asue correctly design pattern - decorator?
I want to increase speed of plane after decorate.
Does decorator always has to add new methods? Can only overwrite existing methods?
This is IPlane interface:
interface IPlane
{
void MoveLeft();
void MoveRight();
Rectangle GetPlaneBody();
int GetHealthPoints();
int GetSpeed();
Bullet Shot();
void SetSpeed(int speed);
}
This is plane class:
public class Plane : IPlane
{
private Rectangle PlaneBody = new Rectangle();
private int HealthPoint;
private int x=200;
private int speed;
private Bullet Amunition = new Bullet();
private static Plane instance;
private Plane() { }
public static Plane Instance
{
get
{
if (instance == null)
{
instance = new Plane();
instance.PlaneBody.Height = 125;
instance.PlaneBody.Width = 115;
instance.PlaneBody.X = 200;
instance.PlaneBody.Y =600;
instance.HealthPoint = 1000;
instance.speed = 10;
}
return instance;
}
}
public void MoveLeft()
{
if(x>-10)
x -= speed;
PlaneBody.X = x;
}
public void MoveRight()
{
if(x<1165)
x += speed;
PlaneBody.X = x;
}
public Rectangle GetPlaneBody()
{
return PlaneBody;
}
public int GetHealthPoints()
{
return HealthPoint;
}
public int GetSpeed()
{
return speed;
}
public Bullet Shot()
{
Bullet bullet = new Bullet();
bullet.SetDamage(Amunition.GetDamage());
bullet.SetSpeed(Amunition.GetSpeed());
bullet.SetCoordinates(x+10, this.PlaneBody.Y - 30);
return bullet;
}
public void SetSpeed( int speed)
{
this.speed = speed;
}
}
This is abstract decorator:
class AbstractPlaneDecorator : IPlane
{
protected IPlane plane;
public AbstractPlaneDecorator(IPlane plane)
{
this.plane = plane;
}
public int GetHealthPoints()
{
return plane.GetHealthPoints();
}
public Rectangle GetPlaneBody()
{
return plane.GetPlaneBody();
}
public int GetSpeed()
{
return plane.GetSpeed();
}
public virtual void MoveLeft()
{
plane.MoveLeft();
}
public virtual void MoveRight()
{
plane.MoveRight();
}
public void SetSpeed(int speed)
{
plane.SetSpeed(speed);
}
public Bullet Shot()
{
return plane.Shot();
}
}
And concrete decorator:
class IncreaseSpeedDecorator : AbstractPlaneDecorator
{
public IncreaseSpeedDecorator(IPlane plane) : base(plane)
{
}
public override void MoveLeft()
{
plane.MoveLeft(); // move two times faster
plane.MoveLeft();
}
public override void MoveRight()
{
plane.MoveRight(); // move two times faster
plane.MoveRight();
}
}
This decorator makes that plane moves 2 times faster (He performs the same method twice). Does it meet the rules of decorator pattern?
I would say the implementation is fine.
I don't know the exact context of your code, but it might be a bit strange that if you ask your decorator for the plane's speed, it will return the plane's base speed, but the plane is moving twice as fast. I think a better name for the decorator to describe its funcionality would be DoubleMoveDecorator or something like that, since it doesn't actually do anything with the plane's speed.
I have a Timer that counts down every 3 seconds (The white circle). It has a script attached called ReloadTimer.
I have a script that fires bullets (TankShooter) and reloads for 3 seconds.
How do I make it so that my countdown starts when I am reloading?
I tried looking at a lot of Unity forums and the advice didn't work.
ReloadTimer.cs
[ExecuteInEditMode]
public class ReloadTimer : MonoBehaviour
{
public Image filled;
public Text text;
public float maxValue = 3;
public float value = 0;
// UpdateReload is called once per frame
public void UpdateReload ()
{
value = Mathf.Clamp(value, 0, maxValue);
float amount = value / maxValue;
filled.fillAmount = amount;
text.text = value.ToString();
}
}
TankShooter
public int m_PlayerNumber = 1;
public Rigidbody m_Shell;
public Transform m_FireTransform;
public AudioSource m_ShootingAudio;
public AudioClip m_FireClip;
public float m_ShellVelocity = 100f;
private string m_FireButton;
public int maxAmmo = 5;
private int currentAmmo;
public float reloadTime = 2f;
private bool isReloading = false;
public ReloadTimer reloadTimer;
public class TankShootingT : NetworkBehaviour
{
public ReloadTimer reloadTimer;
private void Start()
{
if (!isLocalPlayer)
{
return;
}
currentAmmo = maxAmmo;
m_FireButton = "Fire" + m_PlayerNumber;
}
private void Update()
{
if (isReloading)
return;
if (currentAmmo <= 0)
{
StartCoroutine(Reload());
return;
}
reloadTimer.UpdateReload();
if (m_FireButton == "Fire1" && Input.GetButtonUp(m_FireButton))
{
// we released the button, have not fired yet
CmdShoot();
}
}
IEnumerator Reload()
{
isReloading = true;
Debug.Log("Reloading...");
yield return new WaitForSeconds(reloadTime);
currentAmmo = maxAmmo;
isReloading = false;
}
[Command]
private void CmdShoot()
{
currentAmmo--;
// Instantiate and launch the shell.
Rigidbody shellInstance = Instantiate(m_Shell, m_FireTransform.position, m_FireTransform.rotation) as Rigidbody;
shellInstance.velocity = m_ShellVelocity * m_FireTransform.forward;
// Server spawns the shell
NetworkServer.Spawn(shellInstance.gameObject);
m_ShootingAudio.clip = m_FireClip;
m_ShootingAudio.Play();
}
}
For starters, There isn't such thing as UpdateReload that would be "called once per frame" as this is not a predetermined Unity function, it is just a function that you created (You can read about this here). Another problem is that you didn't even call that function anywhere else in your scripts. And even if you did, Mathf.Clamp() needs to be placed in an Update() function so it can update it's value each frame.
I made some modifications to the scripts that you posted, but I haven't tested them yet. give it a try and let me know how it goes:
ReloadTimer.cs
public class ReloadTimer : MonoBehaviour
{
public static ReloadTimer Instance { set; get; }
public Image filled;
public Text text;
public float coolDownTime = 3;
public bool isCoolingDown = false;
void Awake()
{
Instance = this;
}
void Update()
{
if (isCoolingDown == true)
{
filled.fillAmount += 1.0f / coolDownTime * Time.deltaTime;
int percentageInt = Mathf.RoundToInt((filled.fillAmount / coolDownTime) * 10);
text.text = percentageInt.ToString();
}
}
}
TankShootingT.cs
public int m_PlayerNumber = 1;
public Rigidbody m_Shell;
public Transform m_FireTransform;
public AudioSource m_ShootingAudio;
public AudioClip m_FireClip;
public float m_ShellVelocity = 100f;
private string m_FireButton;
public int maxAmmo = 5;
private int currentAmmo;
public float reloadTime = 2f;
private bool isReloading = false;
public ReloadTimer reloadTimer;
public class TankShootingT : NetworkBehaviour
{
public ReloadTimer reloadTimer;
private void Start()
{
if (!isLocalPlayer)
{
return;
}
currentAmmo = maxAmmo;
m_FireButton = "Fire" + m_PlayerNumber;
}
private void Update()
{
if (isReloading)
return;
if (currentAmmo <= 0)
{
StartCoroutine(Reload());
return;
}
reloadTimer.UpdateReload();
if (m_FireButton == "Fire1" && Input.GetButtonUp(m_FireButton))
{
// we released the button, have not fired yet
CmdShoot();
}
}
IEnumerator Reload()
{
isReloading = true;
ReloadTimer.Instance.isCoolingDown = true;
Debug.Log("Reloading...");
yield return new WaitForSeconds(reloadTime);
currentAmmo = maxAmmo;
isReloading = false;
ReloadTimer.Instance.isCoolingDown = false;
ReloadTimer.Instance.filled.fillAmount = 0.0f;
}
[Command]
private void CmdShoot()
{
currentAmmo--;
// Instantiate and launch the shell.
Rigidbody shellInstance = Instantiate(m_Shell, m_FireTransform.position, m_FireTransform.rotation) as Rigidbody;
shellInstance.velocity = m_ShellVelocity * m_FireTransform.forward;
// Server spawns the shell
NetworkServer.Spawn(shellInstance.gameObject);
m_ShootingAudio.clip = m_FireClip;
m_ShootingAudio.Play();
}
}
Hope this helps a bit.