#variables
1 messages · Page 1 of 1 (latest)
let's do this in a thread
show me the code you use for that sanity-drain-zone component
thank you
!code
📃 Large Code Blocks
Large code blocks should be posted as links to services like:
https://gdl.space/, https://paste.ofcode.org/, https://hatebin.com/
https://paste.myst.rs/, https://hastebin.com/
📃 Inline Code
Surround code with three backquotes. Not quotation marks.
To get C# formatting the first line should only contain cs or csharp.
Add a comment with a line number if there is an error message.
```cs
// Your code here
```
Do not share screenshots of code unless requested.
and then show me the inspector for one of the sanity zones
So it doesn't do anything right now?
It does. I can make triggers via box colliders. That all works
my question is getting my sanity to go up when I press the "F" key and turn my flashlight on
this works fine
oh boy.. ummm. yes
It is way better than it was when I started
dont roast me :p
Where were you trying to add that code with the sanitybar?
here ideally
okay, so you first need to give the flashlight a way to find the SanityManager in the first place
It looks like you were trying to use GetComponent to find it.
i did that in the start with getcomponent
i thought you meant where i want it to affect sanity. my bad
Well, both are important
When you call GetComponent<T> in a MonoBehaviour-derived script, you try to find a component of type T on your game object
so GetComponent<SanityManager> would try to find a SanityManager on the flashlight, in this case
That doesn't sound right.
as you've seen here, you can assign a reference to a component in the inspector
That sounds more like what you want.
What if I have public GameObject sanity; then drag the game object in there then do sanity = getcomponent?
GameObject is not a compatible type.
oops, wrong reply
SanityManager would be a valid type.
You can reference anything that's a unity object.
I did do that too. Obviously missing something
GameObject is one, sure, but that's not the right type here.
You don't want literally any game object
that object might not even have a sanity manager on it
You want a SanityManager.
I rarely use GameObject variables.
I only do it when literally any game object would work
(which is very uncommon!)
I use them too much as you can see from the flashlight script
If those variables are just used to activate and deactivate objects, then it's fine
because literally any object will work
but that's not the case with the sanity manager: we can't just assign any random object there
we very specifically need a SanityManager
You've explained that well. I've spent so many hours learning variables and you just made it clear
so, add a new variable that holds a SanityManager. Do it like this:
[SerializeField] SanityManager sanityManager;
You could also do this
public SanityManager sanityManager;
The important thing here is that we need this variable to be serialized. That means it will show up in the inspector and be saved.
Public variables are automatically serialized. Private ones aren't, so you need the [SerializeField] attribute.
Making variables private is good. It reduces the number of ways different parts of your code can mess with each other.
which makes it easier to debug your game when things go wrong
I do private ones a smuch as I can
Once you do this, you'll see a "Sanity Manager" field in the inspector for your flashlight.
Is your flashlight going to be in the scene when the game starts?
rather than being a prefab that you instantiate later
it only becomes active once i pick it up
but it does exist in the scene
that means you can drag the Sanity Manager component into the field
you can just grab the object the manager is attached to
and drag the entire thing into the field
You can also grab a specific component, but that's more annoying (you have to open two inspectors)
now you'll have a reference to it, and can call AffectSanity whenever you need to
That makes so much sense now.
So since I've done this. Do I still need to do getcomponent or has this automatically gotten every component?
Nothing happens "automatically" -- it's just that you've assigned this reference before the game even starts
so you don't need to do it at runtime.
GetComponent should be used when you can't reference the thing you need ahead of time.
For example, I often do this:
void OnTriggerEnter(Collider other) {
if (other.TryGetComponent(out Player player)) {
player.Damage(10f);
}
}
TryGetComponent returns true if it found the component and stores it into its out parameter
this is basically the same as
Player player = other.GetComponent<Player>();
if (player) {
player.Damage(10f);
}
In this case, you obviously couldn't have referenced the player in advance, since you don't know what colliders you're going to be hitting
so you have to use GetComponent or TryGetComponent to see if the thing you hit had a Player
I do sometimes use those methods to save some effort, though
for example, if a component is always on a child of the player, I might just use GetComponentInParent instead of manually assigning the player to all of these different components
Sorry for the delayed replies. I am genuinely interested and absorbing it in
It makes sense. I've only ever used Getcomponent a few times
Also, the reason this was an error was that SanityManager is not derived from GameObject
GameObject and SanityManager have a common parent: UnityEngine.Object
But the inheritance tree diverges there.
GameObject is a direct child, while SanityManager goes through Object -> Component -> Behaviour -> MonoBehaviour -> SanityManager
public class SanityManager : MonoBehaviour means that your class is derived from MonoBehaviour
it's a specific kind of MonoBehaviour
I get that now. I thought everything in the Hierarchy was just "GameObject"
Well, that is kind of true.
Everything you see in the Hierarchy view is a GameObject
when you click on an item in the Hierarchy, the inspector shows you that GameObject
every game object has a Transform (hence it shows up at the top)
Transform holds the position, rotation, and scale. It also holds the parent, if it has one.
this is why you can always write transform in a MonoBehaviour
this is correct. they are GameObjects, but each GameObject is a container holding a list of components, namely, your MonoBehaviour scripts (and by default, the Transform component) . . .
a MonoBehaviour must be attached to a GameObject
and a GameObject must have a Transform
so you always have access to a Transform (and a GameObject)
Other game engines work differently
for example, Unreal doesn't just have GameObject. You can have many different kinds of things in the world.
but in Unity, every single "thing" in the world is a GameObject, with a Transform and, optionally, other components
That's why GameObject is a very non-specific type.
a GameObject variable can reference any "thing" in the world
because every "thing" is a game object
If you want something more specific, you can reference a specific kind of component
You can also reference a Transform. I use that way more than GameObject, actually
it's basically the same thing, because one can't exist without the other
but it does make it more obvious what the variable is going to be used for
public Transform holder;
...
var entry = Instantiate(uiPrefab);
entry.transform.SetParent(holder);
wait, you can just do that directly, can't you
Instantiate(uiPrefab, holder);
It's a useful strategy, although you do sometimes have to rewrite your code when you realize you were too specific!
I'm working on a game where every unit has a bunch of "states" it can be in
I might do this
public EntityAttackState state;
but then I realize there are many kinds of actions the unit should be able to perform here
so I switch to something less specific. maybe just EntityState
but the problem is that I can no longer do things specific to EntityAttackState
i can't set the damage the attack will do, for example
So, the more specific your variable is, the more you can do with it, but the fewer kinds of things you can store in it.
In your case, it's pretty clear that we could only ever use a SanityManager here
it's not like the flashlight can reduce your hunger meter or restore health
if you wanted to do those things, then you'd need to figure out something less specific
(maybe use UnityEvent again!)
UnityEvent is great for allowing a variety of things to happen
you move that logic from the code to the inspector
I am still here. Just processing what you've said.
all good :p
I feel like you're literally pointing at the obvious answer.
we should probably come back down to earth and get back to the original question, lol
so, have you given the flashlight a SanityManager variable and assigned it in the inspector?
Yes, I have
as long as the object holding the SanityManager isn't destroyed, that variable will always be a valid reference to the sanity manager
Once the flashlight is active. It won't be destroyed.
I still am unsure how to implement what I need into the flashlight code.
well, now that you have a reference, you can just call sanitybar.AffectSanity whenever you want
what exactly does "call" mean ? I keep seeing it
calling a method
so, sanitybar.AffectSanity(100); or something
you were calling the Invoke method on those unity events earlier
noted
correct me if I'm wrong. I'm calling the DoorOpens method from "" right?
DoorOpens() is calling a method named DoorOpens in the same class
it's the same as writing this.DoorOpens()
this is a reference to the object whose code you're currently running
(sometimes you have to explicitly write this when things are ambiguous)
public float foo;
public void Method(float foo) {
this.foo = foo;
}
for example
and if you had a reference to the Door class (or whatever this is called)
you could do this
public Door theDoor;
...
theDoor.DoorOpens();
(assuming DoorOpens is public, of course)
I get you
going back to the sanity manager. Where do I call the method. Wherever I put sanitybar, it has red squigly lines under it.
show me what you tried to do.
one sec
in the start method (I was taking reference to the sanity manager script itself as it has something similar)
This in the if flashlight on part. This was one way
oh, you named it sanityManager
I thought you had still named it sanitybar
just use sanityManager
This will replace whatever sanityManager contained with the result of GetComponent<SanityManager>()
If there is no SanityManager on the flashlight, it will return null
oooh. there is no component on it as we did the serializedfield earlier.
well, those are two unrelated things
there is no SanityManager on the flashlight becauase it wouldn't make sense to put it there
There's no reason that GetComponent<SanityManager> couldn't work, even if we also had a serialized field that holds a SanityManager
It's just that, in this case, it won't.
(and it is true that you usually do one or the other, not both)
I still do not know how to call upon the method
sanityManager is the variable that holds a SanityManager
you can access any public field or method of SanityManager with it
I understand that
I also get that. AffectSanity is public
What I mean is I do not know where to call it and how exactly to call it