What i wanted to do
I have a class (BlackBoard) that holdes data. and class NPC Gets the data from (BlackBoard). (NPC_Guard) inherits from (NPC) which uses (NPC_Movement) to move by using the data from (BlackBoard).
BlackBoard class
public sealed class BlackBoard : MonoBehaviour
{
#region Singleton
private static BlackBoard instance = null;
public static BlackBoard Instance
{
get
{
if (instance == null)
{
instance = new BlackBoard();
}
return instance;
}
}
#endregion
[SerializeField] List<Transform> NavigationPoints = new List<Transform>();
public List<Transform> Get_NavigationPoints() => NavigationPoints;
public void Set_NavigationPoints(List<Transform> T) => NavigationPoints = T;
}
NPC_Movement class
public class NPC_Movement
{
Vector3 direction;
List<Transform> _navigationPoints = null;
[SerializeField] public List<Transform> NavigationPoints;
{
get
{
if (_navigationPoints == null)
{
_navigationPoints = BlackBoard.Get_NavigationPoints();
}
return _navigationPoints;
}
}
BlackBoard BlackBoard = BlackBoard.Instance;
public void Move()
{
// A complex movement function which uses NavigationPoints
}
}
NPC class
public abstract class NPC : MonoBehaviour
{
[SerializeField] protected NPC_Movement Movement;
}
NPC_Guard class
public class NPC_Guard : NPC
{
void Update()
{
Movement.Move();
}
}
Problem
NPC_Movement class does not get the NavigationPoints List .
What am i doing wrong
please help
Related
I have this error when i try to complile this C# code on my Unity:
Assets\Scripts\Cauldron.cs(50,57): error CS1503: Argument 1: cannot convert from 'System.Collections.Generic.Queue<System.Collections.Generic.KeyValuePair<PotionCraft.PotionRecipe.Ingredient, uint>>' to 'System.Collections.Generic.Queue<System.Collections.Generic.KeyValuePair<Ingredient, uint>>'
This is the code
using System.Collections.Generic;
using UnityEngine;
namespace PotionCraft.Components
{
public interface IBrewingCauldron
{
public void AddIngredient(PotionRecipe.Ingredient ingredient);
public GameObject BrewPotion();
}
[RequireComponent(typeof(SphereCollider))]
[RequireComponent(typeof(Rigidbody))]
public class Cauldron : MonoBehaviour, IBrewingCauldron
{
public Dictionary<PotionRecipe.Ingredient, uint> Ingredients { get; private set; } = new();
[SerializeField] private SphereCollider cauldronCollider;
private readonly PotionBrewer _potionBrewer = new();
private uint _numberOfIngredients;
private void Awake()
{
cauldronCollider ??= GetComponent<SphereCollider>();
// Set the collider as trigger to interact with ingredients GameObject
cauldronCollider.isTrigger = true;
}
public void AddIngredient(PotionRecipe.Ingredient ingredient)
{
// Keep track of the number of ingredients added
_numberOfIngredients++;
if (!Ingredients.ContainsKey(ingredient))
{
Ingredients[ingredient] = 1;
}
else
{
Ingredients[ingredient]++;
}
}
public GameObject BrewPotion()
{
var ingredientQueue = new Queue<KeyValuePair<PotionRecipe.Ingredient, uint>>(Ingredients);
var potionObject = _potionBrewer.MakePotion(ingredientQueue, _numberOfIngredients);
if (potionObject is not null)
{
Debug.Log($"We made a {potionObject.name} !");
potionObject.transform.position = transform.position;
}
else
{
Debug.Log("We failed to make any potion !!!");
}
Ingredients = new Dictionary<PotionRecipe.Ingredient, uint>();
_numberOfIngredients = 0;
return potionObject;
}
}
}
Edit: This is another code might be related to the problem
using UnityEngine;
namespace PotionCraft.Components
{
public class Ingredients : MonoBehaviour
{
[SerializeField] private GameObject cauldronGameObject;
[SerializeField] private PotionRecipe.Ingredient ingredient;
private SphereCollider _cauldronCollider;
private IBrewingCauldron _cauldron;
private void Awake()
{
if (cauldronGameObject is not null)
{
_cauldron = cauldronGameObject.GetComponent<IBrewingCauldron>();
if (_cauldron is not null) return;
}
var ingredientObject = gameObject;
ingredientObject.name += " [IN ERROR]";
ingredientObject.SetActive(false);
throw new MissingComponentException($"{ingredientObject.name} is missing the cauldron gameobject");
}
private void Start()
{
_cauldronCollider = cauldronGameObject.GetComponent<SphereCollider>();
gameObject.name = ingredient.ToString();
}
private void OnTriggerEnter(Collider other)
{
if (other != _cauldronCollider) return;
_cauldron.AddIngredient(ingredient);
Destroy(gameObject);
}
}
}
So what am I doing wrong here?
The PotionBrewer.MakePotion method accepts an argument of type Queue<KeyValuePair<Ingredient, uint>>.
You are trying to pass it an argument of type Queue<KeyValuePair<PotionCraft.PotionRecipe.Ingredient, uint>> instead.
If PotionBrewer.MakePotion is supposed to accept an argument of the latter type, you might need to add this using alias to your PotionBrewer class:
using Ingredient = PotionCraft.PotionRecipe.Ingredient;
I am building a C# Game Engine for a College Project and I am facing some problems, I have a class called GameObject that contains a List of Component (Which is another Class), I created a class that saves a Vector3 Struct called Transform which Inherits from the Component class.
Now when I try to add the New Instance of Transform into the Component List in Gameobject it doesn't allow me to access the internal methods of the Transform class or do something like get the X coordinate:
// This is the List inside the class GameObject
public List<Component> Components = new List<Component>();
// This is the new Instance of Transform
Transform transform = new Transform();
// This is how I tried to add the new object to the list above
AddComponent(transform);
public void AddComponent(object component)
{
Components.Add((Component)component);
}
// This Works
Console.WriteLine(transform.Position.X);
// However, this line bellow does not allow me to use 'Position'
Console.WriteLine(Components[0]);
The Full Code is Listed Bellow for a Clearer Picture
GameObject Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BoBo3D_George.R_Dor.S
{
public class GameObject
{
// GameObject Class Fields
public List<Component> Components = new List<Component>();
private bool _isEnabled = true;
private string _name;
// ------------------------------
// GameObject Class Constructor
public GameObject(string name)
{
_name = name;
Transform transform = new Transform();
AddComponent(transform);
Rigidbody rigidBody = new Rigidbody();
AddComponent(rigidBody);
Console.WriteLine(transform.Position.X);
Console.WriteLine(Components[0]);
Console.WriteLine(Components[1]);
}
// ------------------------------
// GameObject Class Properties
public string Name
{
get
{
return "Object Name: " + _name;
}
set
{
_name = value;
}
}
public bool IsEnabled
{
get
{
return _isEnabled;
}
}
// ------------------------------
// GameObject Class Methods
public void Disable()
{
throw new System.NotImplementedException();
}
public void Enable()
{
throw new System.NotImplementedException();
}
public void Destroy()
{
throw new System.NotImplementedException();
}
public void AddComponent(object component)
{
Components.Add((Component)component);
}
public void RemoveComponent(object component)
{
throw new System.NotImplementedException();
}
public object GetComponent(int compNum)
{
throw new System.NotImplementedException();
}
}
}
Component, Transform & RigidBody Classes:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BoBo3D_George.R_Dor.S
{
public abstract class Component : IComponent
{
// IComponent Interface Implementation in Component Class
public void OnDisable()
{
throw new NotImplementedException();
}
public void OnEnable()
{
throw new NotImplementedException();
}
public void Start()
{
throw new NotImplementedException();
}
public void Update(float deltaTime)
{
throw new NotImplementedException();
}
}
// Transform Class Componnent
class Transform : Component
{
public Vector3 Position = new Vector3() { X = 0, Y = 0, Z = 0 };
public override string ToString()
{
string info;
info = Position.ToString();
return info;
}
}
// Rigidbody Class Componnent
class Rigidbody : Component
{
private bool _useGravity = false;
private float _g = Physics.Gravity();
private float _timeScale = 0;
private float _fallVelocity = 0;
private float _gravityScale = 0;
private string _info;
public bool UsingGravity
{
get
{
return _useGravity;
}
}
public override string ToString()
{
return $"Gravity:({_useGravity})\n" + _info;
}
public bool ToggleGravity()
{
if (_useGravity == true)
{
_useGravity = false;
}
else
{
_useGravity = true;
}
return _useGravity;
}
public float ActiveGravity()
{
if (_useGravity == true)
{
_timeScale++;
_fallVelocity = _g * _timeScale;
_gravityScale = (_g/2) * (_timeScale * _timeScale);
}
else
{
_timeScale = 0;
_fallVelocity = 0;
_gravityScale = 0;
}
_info = "Time:" + _timeScale + "\nVelocity:" + _fallVelocity + "\nHeight:" + _gravityScale;
return _gravityScale;
}
public void ApplyConstantForce(float incrementation, Vector3 directionInV3)
{
}
}
}
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've been tinkering with this and I have a 'RespawnManager' that I want to use to manage my multiple 'SpawnPoint' classes with different generics but it ended up forcing me to use generics for my 'RespawnManager' which I don't want.
Let's say I had a SpawnPoint<T> class and I made a SpawnPoint<Enemy1>, SpawnPoint<Enemy2>, and SpawnPoint<Enemy3>. Is there any way I can make a list that can just manage multiple 'SpawnPoint's of any generic?
Base class:
public abstract class SpawnPoint<T> : MonoBehaviour
{
//how big the range of the spawn protection is
public int spawnProtectionRadius = 20;
public bool Occupied { get; set; }
public bool IsInSpawn(Transform target)
{
Debug.Log((target.position - transform.position).magnitude);
if ((target.position - transform.position).magnitude <= spawnProtectionRadius)
{
return true;
}
return false;
}
public abstract T Get();
}
Class that Inherits this
public class SeaMineSpawnPoint : SpawnPoint<Seamine>
{
public override Seamine Get()
{
return SeaMineObjectPool.PoolInstance.Get();
}
private void Start()
{
RespawnManager<Seamine>.respawnManager.AddSpawn(this);
}
}
Respawn manager:
public class RespawnManager<T> : MonoBehaviour where T : Component
{
public static RespawnManager<T> respawnManager;
[SerializeField]
private List<Transform> playerList;
[SerializeField]
private List<SpawnPoint<T>> spawnpoints;
private float respawnCounter;
private void Awake()
{
respawnManager = this;
}
private void Start()
{
foreach (SpawnPoint<T> sp in spawnpoints)
{
Debug.Log(sp.transform.position);
}
}
public void AddSpawn(SpawnPoint<T> spawnPoint)
{
spawnpoints.Add(spawnPoint);
}
public void RespawnSeaMines()
{
if (respawnCounter > 5)
{
respawnCounter = 0;
foreach (SpawnPoint<T> sp in spawnpoints)
{
foreach (Transform playerT in playerList)
{
if (sp.Occupied == false && !sp.IsInSpawn(playerT))
{
Component ourGameObj = sp.Get();
ourGameObj.transform.position = sp.transform.position;
ourGameObj.gameObject.SetActive(true);
sp.Occupied = true;
return;
}
}
}
}
}
private void Update()
{
respawnCounter += Time.deltaTime;
Debug.Log(respawnCounter);
RespawnSeaMines();
}
}
ObjectPool
//Class that's used for object pooling of different types.
//'T' must be a Unity component or it will error.
public abstract class ObjectPool<T> : MonoBehaviour where T : Component
{
//An object with this specific component that we use to copy.
[SerializeField]
private T prefab;
//Makes sure that only 1 coroutine runs at a time
private bool coroutineIsRunning;
//The singleton instance to our object pool.
public static ObjectPool<T> PoolInstance { get; private set; }
//A queue is used to organize plus activate and deactivate objects which
//have this component.
protected Queue<T> objects = new Queue<T>();
private void Awake()
{
//Set the instance of this pool to this class instance. Only one of these can be set.
if (PoolInstance != null)
{
throw new System.Exception("Singleton already exists. Cannot make another copy of this");
}
PoolInstance = this;
}
public T Get()
{
//If the queue happens to be empty, then add a brand new component.
if (objects.Count == 0) AddObjects(1);
//Returns the generic component and removes it from the queue.
return objects.Dequeue();
}
public void ReturnToPool(T objectToReturn)
{
//Disables the game object that the T component is attached to.
objectToReturn.gameObject.SetActive(false);
//Stores the T component in the queue.
objects.Enqueue(objectToReturn);
}
public void AddObjects(int count)
{
for (int i = 0; i < count; i++)
{
//Create a new copy of the prefab.
//The prefab is a game object with the T component attached to it.
T newObject = Instantiate(prefab);
//Disable the game object.
newObject.gameObject.SetActive(false);
//Add the T component to the queue.
//The T component is attached to the game object we created earlier.
objects.Enqueue(newObject);
}
}
public T GetWithDelay(int time)
{
T genericToReturn = null;
if (!coroutineIsRunning)
{
coroutineIsRunning = true;
StartCoroutine(GetCoroutine(time, genericToReturn));
}
return genericToReturn;
}
private IEnumerator GetCoroutine(int time, T generic)
{
float counter = 0;
while (counter < time)
{
counter += Time.deltaTime;
yield return null;
}
generic = Get();
generic.gameObject.SetActive(true);
coroutineIsRunning = false;
}
}
You should be able to declare your spawnpoints property in RespawnManager as a List<SpawnPoint<Component>> instead of List<SpawnPoint<T>>. That will allow you to get rid of the <T> type parameter entirely from RespawnManager and make it non-generic.
I'm trying to make a music application.
I would like to be able to change within the AudioMixer between different sound groups using the same GameObject.
Is it possible to change the PianoMixer source with another script at runtime?
public class PianoAudioManager : MonoBehaviour{
public PianoSound[] PianoSounds;
public static PianoAudioManager instance;
public AudioMixerGroup PianoMixer;
void Awake()
{
if (instance == null)
instance = this;
else
{
Destroy(gameObject);
return;
}
DontDestroyOnLoad(gameObject);
foreach(PianoSound s in PianoSounds)
{
s.source = gameObject.AddComponent<AudioSource>();
s.source.outputAudioMixerGroup = PianoMixer;
s.source.clip = s.clip;
s.source.volume = s.volume;
s.source.pitch = s.pitch;
}
}
}
I tried something like this, but I always get errors
public class Octaves : MonoBehaviour
{
public GameObject PianoAudioManager;
public void OctaveDown()
{
AudioMixer audioMixer = Resources.Load<AudioMixer>("Scales/Sounds");
AudioMixerGroup[] audioMixGroup = audioMixer.FindMatchingGroups("Master/PianoDown");
PianoAudioManager.outputAudioMixerGroup = audioMixGroup[0];
}
}
I would be very grateful for any help, thank you very much.
I finally get the answer.
Right click on the parameter name "Pitch" and choose "Expose 'Pitch' to script".
using UnityEngine.Audio;
public class Octavas : MonoBehaviour
{
public GameObject PianoAudioManager;
public void OctaveDown()
{
AudioMixer audioMixer = Resources.Load<AudioMixer>("Scales/Sounds");
audioMixer.SetFloat("PianoPitch", 0.5f);
}
}