Host Data Object set to Null Reference Unity3D? - c#

I am writing a multi player game. And doing a check OnGUI() that if there is any hostData do something.
if (hostData)
{
for (int i = 0; i < hostData.Length; i++)
{
GUI.Button (new Rect (btnX * 2f + btnW, btnY * 1.2f + (btnH * i), btnW * 3f, btnH * 0.5f), hostData [i].gameName);
}
}
But I have filled host Data on a button click, while on the other hand OnGUI is always looking for if(hostData) that is why it gives Null reference.
How i check this if statement other then this. Help me out.

if (hostData) only works if hostData is a game object, or component. This is because Unity implemented the implicit operator.
In other words, if (gameObject) works as a shortcut to if (gameObject != null).
This doesn't work when you are using something else then game objects or components, such as arrays or lists. In that case you have to use != null.

Related

Why do my blocks get stuck and refuse to fall to the lowest level?

In my grid-based blocks game I had trouble with the falling code for the game's blocks.
Here's the code snippet:
for (int i = (int)transform.position.y; i >= 0; i--)
{
if (transform.position.y >= 0 && SpawnBlocks.allBlocks[(int)gameObject.transform.position.x, i] == null)
{
float timeElapsed = 0;
int initPos = (int)transform.position.y;
int targetPos = (int)transform.position.y - i;
timeElapsed += Time.deltaTime * 4;
float moveDown = Mathf.Lerp(initPos, targetPos, timeElapsed);
transform.position = new Vector2(transform.position.x, moveDown);
SpawnBlocks.allBlocks[(int)transform.position.x, (int)transform.position.y] = gameObject;
gameObject.name = "(" + transform.position.x.ToString() + "," + transform.position.y.ToString() + ")";
}
}
Each block checks through a list to see whether there is a block beneath it. If there isn't, then it should smoothly lerp down that many blocks to fill it in.
There are three problems occurring however:
Blocks do not fall down to the lowest row
Even after one block has fallen down, blocks above that block in the same column won't go down and will be stuck up there.
If there is only a single space between blocks, then the block above will only move .016694 rather than a full 1
Instead of actually Lerping, blocks would just appear at the space beneath.
I do not know why the blocks act like this.
Here's an example pic of what is happening:
Image 1
And here's an edited version showing what should happen:
Image 2
SpawnBlocks.allBlocks[(int)transform.position.x, (int)transform.position.y] = gameObject; can make this false SpawnBlocks.allBlocks[(int)gameObject.transform.position.x, i] == null, then transform.position = new Vector2(transform.position.x, moveDown); will not be executed, so block can only drop a little bit before stopping.
Also I suggest not to use float for indexing. Try using int for logic, and trigger sort of coroutines for dropping animations.

Jittering when rotating and then translating a matrix in XNA/Monogame

I'm having a problem in Monogame/XNA where I am storing the position/rotation/scale in a matrix for easier manipulation of these values with parenting. It all seems to be going well, except for when I rotate the matrix, which is when the object seems to jitter around and shake. Here is the relevant code:
// Executes every frame
internal void Draw()
{
float RadRot = MathHelper.ToRadians(Rotation);
// Sets world matrix for things that draw
if (Parent != null) {
WorldMatrix = Matrix.CreateScale(Size.X, Size.Y, 1) * -Matrix.CreateTranslation(Pivot.X, Pivot.Y, 0) * Matrix.CreateRotationZ(RadRot);
WorldMatrix.Translation = Vector3.Zero; // Rotating seems to create a strange positioning issue, this fixes it
WorldMatrix *= Matrix.CreateTranslation(RelativePosition.X, RelativePosition.Y, 0) * Matrix.CreateRotationZ(MathHelper.ToRadians(Parent.Rotation)) * <FIX JITTER> * Matrix.CreateTranslation(Parent.DecomposedPosition.X, Parent.DecomposedPosition.Y, 0);
} else
{
// For objects without parents
WorldMatrix = Matrix.CreateScale(RelativeSize.X, RelativeSize.Y, 1) * -Matrix.CreateTranslation(Pivot.X, Pivot.Y, 0) * Matrix.CreateRotationZ(RadRot);
WorldMatrix.Translation = Vector3.Zero; // This fixes the jitter issue, but in the code above (in the if statement), I can't do this when translating the child around the parent
WorldMatrix *= Matrix.CreateTranslation(RelativePosition.X, RelativePosition.Y, 0);
}
Vector3 TempPos = Vector3.Zero;
Quaternion TempRot = Quaternion.Identity;
Vector3 TempSize = Vector3.Zero;
WorldMatrix.Decompose(out TempSize, out TempRot, out TempPos);
DecomposedPosition = new Vector2(-TempPos.X, -TempPos.Y);
DecomposedRotation = MathHelper.ToRadians(Rotation); // Can't convert quaternions, but this works
DecomposedSize = new Vector2(MathF.Round(TempSize.X), MathF.Round(TempSize.Y));
foreach (Component2D comp in Components)
{
comp.Draw();
}
}
This is what comp.Draw calls:
MyGame.SpriteDrawing.Draw(Image, new Rectangle(LinkedObject.DecomposedPosition.ToPoint(), LinkedObject.DecomposedSize.ToPoint()), RenderRegion, Color, LinkedObject.DecomposedRotation, LinkedObject.Pivot, SpriteEffects.None, LinkedObject.Layer + (SubLayer / 10000));
Here is what it looks like in action:
EXTRA NOTE: This jittering does occur no matter the scale of the objects
Give it a try to organize the scene in a different manner:
Each object let store its scale (Vector3), rotation (Quaternion), and position (Vector3)
Each object should have a property of result matrix (in local space), which will be the multiplication of something like this in following order: Matrix.CreateScale(scale) * Matrix.CreateRotationQuaterion(rotation) * Matrix.CreateTranslation(position)
Now, when you have the above local space Matrix, use it to create WorldMatrix, which is a multiplication of Parent World Matrix and this object local space Matrix, or local space Matrix only - when no Parent is present.
Try to pass only the world matrix of each element to your drawing code, avoid decomposition
If you have a large hierarchy, you could cache local matrix results if it is not changed
It seems that I was simply using the wrong SpriteBatch.Draw(). I was using the Rectangle version, whereas all I needed was to use the Vector2 version to prevent rounding errors.
MyGame.SpriteDrawing.Draw(Image, LinkedObject.DecomposedPosition, RenderRegion, Color, LinkedObject.DecomposedRotation, LinkedObject.Pivot * RenderRegion.Size.ToVector2(), LinkedObject.DecomposedSize / RenderRegion.Size.ToVector2(), SpriteEffects.None, LinkedObject.Layer + (SubLayer / 10000));

Player Shooting using blend tree and C#

I'm using C# and Unity for a shooter game. My code works, but I'd like to tweak it. I have this on a blend tree and am using which direction the player is in to fire the bullet. The problem is, if you rapidly change directions, the player doesn't always shoot. I found this to be because the full value of 1 or -1, isn't always being achieved. If I put "less than or equal to" as opposed to "equals (==)", the bullets fire all the time as it is always "less than" at that point. Is there a different way of doing this?
Thank you in advance.
Example of my code, these are only 2 directions to save space, it is a 4 directional sprite. I apologize if the code is broken up, I don't know how to show it properly here.
if (myAnimator.GetFloat("DirectionX") == -1f)
{
shotTime = Time.time + timeBetweenShots;
GameObject b = (Instantiate(bulletLeft, shotPoint.position + -transform.right, Quaternion.identity));
b.GetComponent<Rigidbody2D>().AddForce(-transform.right * speed);
}
if (myAnimator.GetFloat("DirectionY") == 1f)
{
shotTime = Time.time + timeBetweenShots;
GameObject b = (Instantiate(bulletUp, shootUpPoint.position + transform.up, Quaternion.Euler(0, 0, 90)));
b.GetComponent<Rigidbody2D>().AddForce(transform.up * speed);
}
Sounds like your looking for discreet integer values:
int dirX = Mathf.RoundToInt(myAnimator.GetFloat("DirectionX"))
if(dirX == 1)
//etc

How can I cull my prefabs that aren't inside the 2D Camera View in Unity

I'm working on replicating the game "Deepworld". I setup world gen using array maps and some special logic. I'm creating hundreds of objects in seconds. This destroys performance.
Even hitting the play button takes a while, and it's pretty hard to "exit" play mode, as it's basically 1 fps.
How should I go about culling everything not in the camera view. I don't understand any logic around the camera's view within C#.
If I knew more about how I could access the actual location and size of the camera's view, I could probably do something along these lines.
... {
for (int y = 0; y < height; y++) {
Vector3 pos = new Vector3(-width / 2 + x + 0.5f, objectHolder.transform.position.y, -height / 2 + y + 0.5f);
// Imaginary If Conditions Ahead
if (pos.x <= CameraViewMaxX && pos.x >= CameraViewMinX && pos.y <= CameraViewMaxY && pos.y >= CameraViewMinY) {
Gizmos.color = (map[x, y] == 1)? Color.white : Color.clear;
Gizmos.DrawCube(pos, Vector3.one);
if (map[x, y] == 0) {
Instantiate(block, pos, objectHolder.transform.rotation);
}
}
// Back to Normal
}
}
I don't know what direction to go in, and I don't know how to physically implement this into my game.
I know that I'm only supposed to load blocks in the view, like Terraria or Deepworld. That's the only reason those games run smoothly. It's because of the culling.

XNA Simple Tile Map collisions

I'm new at this and I'm making a very simple 2D platformer with a level is loaded from a text file. I'm having trouble to try how to figure out how I can have my character sprite collide with the tiles.
This is an example of a .txt that my game will run:
1,1,1,1,1,1,1,1,
1,1,1,0,0,0,0,1,
1,1,0,0,0,1,0,1,
1,0,0,0,0,1,1,1,
1,0,0,0,0,0,0,1,
1,0,0,0,1,0,0,1,
1,S,0,1,1,0,F,1,
1,1,1,1,1,1,1,1,
I've managed to figure out how to successfully draw them onto the page, but cannot progress further.
My current model has my character colliding with the edge of the screen by having a boolean for Collision equal to true when the edge of the sprite touches the edge of the screen and setting its velocity to 0, but I'm not sure how to do that to block that are generated from a .txt
My current model of drawing a level looks like this:
if (currentState == GameState.Playing)
{
for (y = 0; y <= 7; y++)
{
string[] mapchars = maplines[y].Split(','); //where maplines is each row of characters and mapchars is each individual character//
for (x = 0; x <= 7; x++)
{
if (mapchars[x] == "1")
{
spriteBatch.Begin();
spriteBatch.Draw(block, new Vector2((200 + (50 * x)), ((50 * y))), Color.White);
spriteBatch.End();
}
if (mapchars[x] == "F")
{
spriteBatch.Begin();
spriteBatch.Draw(block, new Vector2((200 + (50 * x)), ((50 * y))), Color.Yellow);
spriteBatch.End();
}
if (mapchars[x] == "S")
{
spriteBatch.Begin();
spriteBatch.Draw(sprite, new Rectangle((200 + (50 * x)), ((50 * y)), 40, 40), Color.White*0.5f);
spriteBatch.End();
}
if (x > 7)
{
break;
}
}
if (y > 7)
{
break;
}
}
}
Where maplines[] is each line of the .txt and where mapchars[] is for each individual character on each line.
If anyone knows a solution to this problem, it would be a great help :)
Thanks.
Don't do that like this ! You are wasting a lot of speed with a game coded like this. I have an issue for you.
First, get all your .txt map into a string[] wich is line is an string. Do that with the method File.ReadAllLines(string yourtxtfilepath).
Once you have done this, create an new 2 dimensional array of Block (Block[,]). You have to create an general abstract class Block wich all your types of blocks (rock, air, grass ...) inherits from its.
Create a for loop who checks all chars in all the string of the array of string you got. In that loop check if the character is an '1' or an 'F' or something else by a case statement. For example, if it was an 'F' add a new GrassBlock to your Block 2 dimensional array.
Finally, after the loop you get your map in your 2 dimensional Block array, wich is perfect to get access to all your blocks in the map.
Just put a foreach loop in the Draw() method to draw each block to your screen by incrementing their positions by the width and the heights of your tiles.
If you don't understand what I said, just do some Google searches to get the necessary knowledge so you will understand. Start by acknowledge what I try to explain you and after, you can concentrate yourself on collisions, wich is more advanced.

Categories