Using Content.Load<> in a class/subclass - c#

I'm wondering if there is anyway to use the "Content.Load<>" in a class that is not the game itself, say I want to load a texture from within the class, rather than sending the texture to it.
namespace ProjectGame1
{
public class Ship
{
public Texture2D texture;
public Ship()
{
this.texture = Content.Load<Texture2D>("ship");
}
}
}
That's an example of what I'm trying to achieve

You just need to pass your ContentManager to the Ship object:
public Ship(ContentManager content)
{
this.texture = content.Load<Texture2D>("ship");
}
From your game class you instantiate the Ship:
Ship ship = new Ship(this.Content);

First of all, I recommend not using DrawableGameComponent, my reasoning for this is outlined in this answer here.
Now, to make your code work as-is, you need to pass a ContentManager into the constructor you are creating (see JoDG's answer). But to do this you must only construct it after the ContentManager is ready. For Game's content manager, this is during and after LoadContent being called (so not in your game's contstructor or Initialize method).
Now, you could do something like using DrawableGameComponent, which is much nicer: Just give your Ship class a LoadContent method, and call that from your game's LoadContent (as you would do for Draw and Update).
If the texture that your ship uses is not part of your ship's state (ie: all ships use the same texture), you could even make it static, saving you from having to call LoadContent on every ship you create. I have an example of this is this answer here, which also has a list of other useful information about Content Manager.

If the class derive form DrawableGameComponent then you still can use
Game.Content.Load<Texture2D>("ship");

In order to get this to work, you'll need a Constructor that accepts a parameter of type Game. This will mean you'll need to add a reference to Microsoft.Xna.Framework.Game.
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
namespace ProjectGame1
{
public class Ship : DrawableGameComponent // Notice the class now inherits from
{ // DrawableGameComponent
public Texture2D texture;
public Ship(Game game)
: base(game) // <<---- Don't forget to pass Game to the base constructor
{
this.texture = game.Content.Load<Texture2D>("ship");
}
}
}

I think you'll need a reference to the Game object to get its Content member. This could either be passed in or you could make the game a Singleton.

Okay I solved it, I used a different method since yours didnt quite work as I'd expect.
What I did was make a "public static ContentManager asd;" and then assigned it to Game's ContentManager, and then it worked by redirecting it to "Game1.asd
(Variable names are examples)

Related

Object Reference Not Set to an Instance - Unity2D

I have this simple code to change the sprite of an image everytime I click a button.
using UnityEngine;
using UnityEngine.UI;
public class SampleChange : MonoBehaviour {
public Sprite sampleSprite;
public Image sampleImage;
public void Start()
{
sampleImage = GetComponent<Image>();
}
public void changeColor()
{
sampleImage.gameObject.GetComponent<Image>();
sampleImage.sprite = sampleSprite;
}
}
I attached this script to an EmptyGameObject and Loaded the function on the Button that is parented on a Canvas alongside the Image. I already also placed the Image and Sprite objects in the inspector:
Inspector Settings
When I run the game and click the Button, it gives me this error:
NullReferenceException: Object reference not set to an instance of an object
SampleChange.changeColor () (at Assets/Scripts/SampleChange.cs:18)
The cs:18 is the sampleImage.sprite = sampleSprite;. I really don't know why it's not working.
OK simple,
public Image sampleImage;
that means
you will set "sampleImage" variable in the inspector, in the editor, before you hit Play
But this one ..
sampleImage = GetComponent<Image>();
means
you will set "sampleImage" variable in code when the scene is running.
You have to sort it out and do it "one way or the other".
Suggest you use the first method while U learning.
(If you do use the second method, the "Image" must actually be on the game object which is holding the script in question. If you struggle with that, I would urge you to ask a separate question, or just study up on the basics using Unity tutorials.)
Cheers
It appears that you have no constuctor defined for your class and that you are just trying to call the changeColor() method as if it were a static function of the class. You need to construct objects of your class and then call the methods you defined on those objects, not on the class itself.

What is MonoBehaviour in Unity 3D?

using UnityEngine;
using System.Collections;
public class VariablesAndFunctions : MonoBehaviour
{
int myInt = 5;
}
The full code is here Unity Official Tutorials
What is the purpose of MonoBehaviour
MonoBehaviour is the base class from which every Unity script derives. It offers some life cycle functions that are easier for you to develop your app and game.
A picture is worthy of thousands of words.
Source of the image: https://docs.unity3d.com/uploads/Main/monobehaviour_flowchart.svg
While the following statement is correct,
"MonoBehaviour is the base class from which every Unity script derives" -
I honestly feel it can be misleading to beginners. The phrase - "every Unity script" - being the culprit.
It gives a beginner the notion that all scripts created in unity must extend Monobehaviour. Which is not the case. You can create scripts that house classes that extend the c# base object class. In doing so, your script is then categorised as not a Unity script but nothing stops it from interacting with other Unity scripts and vice versa.
MonoBehaviour is another class that VariablesAndFunctions is inheriting from. This allows the inheritor to use the methods and variables of the other class providing they have the correct access level modifier set.
In the below example Class1 inherits from Base and so can use the protected method Method1
public class Base
{
protected void Method1 { /*...*/ }
}
public class Class1 : Base
{
public void Method2 { Method1(); }
}
Note in this particular example it would be better for Method1 to be marked as abstract or virtual so then Class1 can override it like so:
protected override Method1()
{
//...
base.Method1(); //Call the implementation of Method1 in Base here
//...
}
In particular though MonoBehaviour is described as being:
MonoBehaviour is the base class from which every Unity script derives.
Therefore when doing scripting in unity, you use this base class to better control how things are accessed so you do not need to do it yourself.
Monobehavior is what most of your scripts inherit from,
if you go to the documentation Click here!
you will see a bunch of variables and methods you get from this Inheritance.
such as:
Public Methods
Messages
Properties
Public Methods
Static methods
The most commonly used method (its under message in the documentation but honestly its better to see it as a function) is Update , its the main game loop, the speed at which the update function is called is based on your fps. But the important thing to take away is that if you didn't inherit from monobehavior, you wouldn't have access to this game loop.
Another important function that you get from Monobehavior is Start, which is called once on a script, and it's called after awake, so if you want to set some variables up you can do it here.
The important thing to take is that if you made a simple C# class that inherits from nothing, you wouldn't have access to these methods discussed. Monobehavior gives you access to many functions that help you build your game.
There are other behaviors your scripts can inherit from like ScriptableObject and StateMachineBehaviour, which give you access to other methods, but Monobehavior is the most common behavior your scripts will inherit from.
It's also good to note that whenever you use Monobehavior, it comes with a transform, some other scripts (Scriptable objects) don't come with a transform. The transform is simply a position in your game/scene where the gameobject lies its an x,y,z coordinate with rotation and scale.

Declare a variable class

i need to declare a variable class in my code so i can access a function (having the same name in all classes) but doing each time a different behavior).
and this is my code:
using UnityEngine;
using System;
using System.Collections;
public class Bubble : ItemBehaviour
{
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
}
void OnMouseDown ()
{
theclass.Behaviour ();
}
}
knowing that (theclass gonna be variable ).
Thank you guys for your answer but it is a bit special.
My game is about interaction between player and game objects when the player approach any item that is "interactible" lets say, a bubble shows up, this bubble is a GameObject and it is the same for any object that allow interactions,
So since i am doing a 2D game i thought, it would be great if i make a "universal"
EmptyGameObject that contains all common aspects that anyObject would contain, and i grouped main functions and common ones in a general script and i added it to this emptyGameObject, then i added the Bubble prefab to this Game object and i a dded a code to it this code contains what i wrote in my firs post.
i was thinking that now each time i want an object i just drop this emptygameobject prefab and changes sprites and characteristics.
And each object have a different behavior (ex: i can delete an apple as if the character consumed it but i can not consume a door, the door would rather trigger an animation than being destructed ) i am specifying all this in a class for each item.
now whatever the class is (the object is) the trigger is in the bubble class (which i posted first) but the class will be different each time and i can not make a class that contains polymorphism because its not the same context each time.
I think you should create an interface that declares all the functions you would like to use in different classes.
interface IBehaviour
{
void Behaviour();
void AnotherBehaviour();
}
with this you define a behaviour what a class, which implements the interface, is capable of.
And then your classes would be:
class MyClass1 : Ibehaviour
{
}
class MyClass2 : IBehaviour
{
}
Apart from this you can use abstract classes. There are a lot of well-written articles about these topics on the Internet.
Firstly, I recommend to get familiar with OOP principles.
This link is a good way to start.
Good luck.
Thank you all,
The matter was solved by creating a global (abstract) gameOject that contains the class that we want to inherit from, and then each time the gameObject atached to this class calls (Behavior function) it trigger whatever the override is for this function for this object.

seting universal spawn prefab

we've been banging our heads with this one, in theory, having a public static object to hold the prefab which is to be spawned should have solved this, but the script gets a static variable when the static keyword is not there, but still the objects get individual variables, while when I add the static keyword, the script's variable disappears. Are we doing something wrong? This is the exact definition:
public static Object prefab;
I too am still new with Unity, but will offer some personal research / findings. I too hate to explicitly have some object with public properties exposed so you can "stick" an object prefab in a scene. If trying to build a system / game components dynamically, knowing what / when to add would be your discretion. I too liked the approach of having a STATIC available so you can just go to it at any time you needed another "thing".
I found that using "Resources" could allow you to load a prefab via code without the need of having a scene object to drag controls to, such as for a master list.
In you default "Assets" folder, Create a folder "Resources" (not sure if case-sensitive). Anyhow, I put all my other stuff in respective folders under that... materials, prefabs, sprites, textures, whatever... So now, in my "Prefab" folder, I could have a prefab for a "Hero", "Laser", "Shield", whatever.
Now, how to get these pieces into your STATIC class. You could create a special method that you call to just load them via the resources class of Unity, then, create function that will return a CLONE of the item in question. This way, you leave the original alone, and have your own to work with in your game as needed.
Something like...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using System.Collections;
namespace Assets.Scripts
{
public static class MyGameObjManager
{
private static bool alreadyLoaded;
public static GameObject myHero { get; private set; }
public static GameObject myWeapon {get; private set;}
public static void LoadObjects()
{
if (alreadyLoaded)
return;
// Load the resource which is RELATIVE to the "Resources" path...
myHero = (GameObject)Resources.Load("Prefab/Hero");
// This OTHER appears to load at a SPECIFIC Path allowing it to go to the root level ASSETS
myWeapon = (GameObject)Resources.LoadAssetAtPath("Assets/Resources/Prefab/Weapon", typeof(GameObject));
alreadyLoaded = true;
}
}
public class GameMgr2 : MonoBehaviour
{
public static GameObject GetHero()
{
MyGameObjManager.LoadObjects();
return (GameObject)Instantiate(MyGameObjManager.myHero, new Vector3(0, 0, 0), new Quaternion());
}
public static GameObject GetWeapon()
{
MyGameObjManager.LoadObjects();
return (GameObject)Instantiate(MyGameObjManager.myWeapon, new Vector3(0, 0, 0), new Quaternion());
}
}
}
So, the STATIC class CAN NOT derive from MonoBehavior which allows the "Instantiate" call to create the clone of the object and return it. So, I created a SECONDARY non-static class that IS derived from MonoBehavior and put static methods that call the static game object manager to get the prefabs I need.
AGAIN, I too am still learning, but hope this helps you some with your design considerations... As for the calling to get the hero or weapon, you could obviously parameterize it by passing in its Vector3 coordinate, or Quaternion value, but you can run with it.
STATIC vs NOT
Per your code and making it a STATIC means a single instance no matter how many of the class are put anywhere within the system. So if you have 5 prefabs on a screen and try to put each one to a different "thing", it will overwrite with whatever one was assigned last. Having the property as just "public" will allow you to have 5 prefabs on a screen and then drag/drop different "things" on each respectively and each will retain their own "thing" instance.
Sorry I can't advise more without knowing what you are trying to implement.
non-static should help within the editor by drag/drop. However, STATIC

Calling a method from a created instance

First post so hi! (please correct me if I use some term wrong)
I've got a class Screen in which I create an instance of another class named Player (let's call this instance Player). Now, in Screen I have a method called ResetHUD which I would like to call from Player.
How would I do that? The only code inside ResetHUD is 1 line which sets a variable to another variable. As far as I know I can use EventHandler (but since ResetHUD doesn't need any arguments I'm thinking that I'm using that wrong) or delegates (which I have no idea how to use).
Help is appreciated!
It sounds like you have a containment relationship... the Screen object contains one (or more?) Player objects.
When Screen creates Player, it can set a property on Player indicating the parent (creating) Screen object.
class Player
{
private Screen parentScreen;
public Player(Screen parentScreen) { this.parentScreen = parentScreen; }
public MyMethodThatHasToCallScreensMethod()
{
parentScreen.ResetHUD();
}
}
class Screen
{
public Player CreatePlayer()
{
return new Player(this);
}
}
You can also use events (events by the way can have parameters, or not, depending on what you need).
This is my favorite tutorial on events and delegates in C#. Starts simple and builds on each step.
http://www.akadia.com/services/dotnet_delegates_and_events.html
Put a MyScreen property on the Player class. When you create the Player class, set that property to your screen class. You now have a reference to screen that you can call from inside player.
Well, something in Player needs to have a reference to the Screen instance. Options:
When you create the Player, pass this to the constructor so that it can remember the Screen it belongs to
Create an event on Player and subscribe to it from Screen
Pass the Screen along as parameters along the method call chain involved (this may not be practical in your situation)

Categories