Unity Physics.OverlapBox just doesn't work - c#

So there is a problem that whenever I use Physics.OverlapBox to check how many objects in that area exist it always output 0.
Here is my stripped down code:
void Update () {
a();
}
void a()
{
Collider[] c = Physics.OverlapBox(new Vector3(10, 10,10), new Vector3(-10, -10, -10));
Debug.Log(c.Length);
}
My scene setup:
A simple cube placed at position(0,0,0) with scale of (1,1,1)
An empty object where I attach this script
As you can see, my OverlapBox bounds are much bigger than my cube, so it should find my cube, right? Well, no. The output I get from the console is 0.
One more thing: if I set the scale of that cube to something higher than 40 in all axis, the script finally detects my cube and outputs 1.
How do I get this working so the script would find my cube with default scale?

I had this same issue. I was using TransformVector to calculate the size of my box:
Vector3 size = itemTransform.TransformVector(itemCollider.size / 2);
Collider[] results = Physics.OverlapBox(itemTransform.position, size);
The results weren't consistent. I realised that TransformVector was returning negative values for the size so I simply had to Mathf.Abs the Vector:
Vector3 size = itemTransform.TransformVector(itemCollider.size / 2);
size.x = Mathf.Abs(size.x);
size.y = Mathf.Abs(size.y);
size.z = Mathf.Abs(size.z);
Collider[] results = Physics.OverlapBox(itemTransform.position, size);

According to the documentation, you are setting the size of the overlapping box to -20, -20, -20, which is not quite logic. It could explain why you have to set the scale of your cube to something bigger than 40, 40, 40.
Also, Physics-related operations should be processed in the FixedUpdate function instead of the Update one

Related

Bug with Unity3D's LookAt function in AR Foundation for Android

I'm having a problem regarding my simple shooting game in AR using AR foundation.
First of all i need to explain how the app works:
-> it detects 5 planes and puts in the centre of them a cube, then saves the cube and the related plane in a struct:
`
public void PlaneUpdated(ARPlanesChangedEventArgs args)
{
if (args.added != null && planes.Count < maxObjects)
{
ARPlane arPlane = args.added[0];
PlaneObj temp = new PlaneObj(arPlane, (Instantiate(PlaceablePrefab, arPlane.transform.position, Quaternion.identity)));
planes.Add(temp);
}
}
`
-> after 5 blocks are placed a button appears which, when clicked, calls the function Update Size which moves a trigger block collider in the position of the camera and calls for updateObjects function
`
public void UpdateSize()
{
if (canUpdate)
{
canUpdate = false;
lookPoint.transform.position = Camera.main.transform.position;
this.GetComponent<UpdateObjects>().updateObjects(planes, lookPoint); //changed to lookPoint
}
}
`
-> the updateObjects function takes everyn object placed, scales them with a fixed ratio and then calls the LookAt function which turns every block towards the position of lookPoint
`
public void updateObjects(List<PlaceObjectsAutomated.PlaneObj> planes , GameObject lookPoint)
{
foreach(PlaceObjectsAutomated.PlaneObj planeObj in planes)
{
// var scaling = new Vector3(planeObj.plane.size.x * 2, planeObj.plane.size.y * 2, 0); //planeObj.obj.transform.localScale.z);
var scaling = new Vector3(1, 1, 1); /////////
planeObj.obj.transform.localScale += scaling;
planeObj.obj.transform.LookAt(lookPoint.transform.position);
}
this.GetComponent<SpawnEnemy>().spawnEnemy(planes, lookPoint);
}
`
Here's what the bug is: at this point i have 5 scaled blocks that look towards that point, but then after a while, without any other code except these snippets that controls the cubes rotation, they go back to their original rotation and will not rotate anymore, even if i try to call for LookAt again.
Does anyone knows why is it doing this? this problem happens only in AR, because
The things i know for sure are:
-This is not caused by the struct, it happened even before i used that
-The LookAt function isn't called anywhere else nor i manipulate the block's size and rotation except for the updateObjects function
-This is not cause by the scaling, because it happens even if i don't scale the blocks
-The functions aren't called except when i need them to, so there's no instances where it might go through them a second time
-This is not affected by the Quaternion.Identity because in the dummy 3d project i used to test the features the blocks stay rotated even with Identity as the initial spawn rotation
-I know they can't be rotated after they snap back to their original rotations because i actually tried to call the LookAt function afterwards but it doesn't work

GUIText is behind GUITexture

First off I have looked around and I can see many posts about this and they all point towards the Z position of the text, however I have changed this to minus and positive and my text is always drawn behind my GUITexture.
So this is what I have setup
My GUI has 4 text boxes
Score
Lives
Level
Time
Now I have an object called GameManager which uses this code below to draw my two GUI sprites
void OnGUI()
{
float screenHeight = Screen.height / 12f * 1.5f;
GUI.DrawTexture (new Rect (0, 0, Screen.width * 2, screenHeight), textureBand);
GUI.DrawTexture (new Rect (0, Screen.height - screenHeight, Screen.width * 2, screenHeight), textureBand);
}
However what ever I do my text is always drawn below my GUITexture so I can never see my text, could I get a little help with this one.
If you're drawing into the same location, you need to specify the depth of each draw to make sure they're sorted correctly. Take a look at the unity docs here:
http://docs.unity3d.com/ScriptReference/GUI-depth.html
Set a higher depth value for the textures you want drawn further back (behind the text) like so:
GUI.depth = 1;

Create Rect at global coordinate

My scene is 2048 x 1152, and the camera never moves. When I create a rectangle with the following:
timeBarRect = new Rect(220, 185, Screen.width / 3, Screen.height / 50);
Its position changes depending on the resolution of my game, so I can't figure out how to get it to always land where I want it on the screen. To clarify, if I set the resolution to 16:9, and change the size of the preview window, the game will resize at ratios of 16:9, but the bar will move out from where it's supposed to be.
I have two related questions:
Is it possible to place the Rect at a global coordinate? Since the screen is always 2048 x 1152, if I could just place it at a certain coordinate, it'd be perfect.
Is the Rect a UI element? When it's created, I can't find it in the hierarchy. If it's a UI element, I feel like it should be created relative to a canvas/camera, but I can't figure out a way to do that either.
Update:
I am realizing now that I was unclear about what is actually being visualized. Here is that information: Once the Rect is created, I create a texture, update the size of that texture in Update() and draw it to the Rect in OnGui():
timeTexture = new Texture2D (1, 1);
timeTexture.SetPixel(0,0, Color.green);
timeTexture.Apply();
The texture size being changed:
void Update ()
{
if (time < timerMax) {
playerCanAttack = false;
time = time + (10 * Time.deltaTime);
} else {
time = timerMax;
playerCanAttack = true;
}
The actual visualization of the Rect, which is being drawn in a different spot depending on the size of the screen:
void OnGUI(){
float ratio = time / 500;
float rectWidth = ratio * Screen.width / 1.6f;
timeBarRect.width = rectWidth;
GUI.DrawTexture (timeBarRect, timeTexture);
}
I don't know that I completely understand either of the two questions I posed, but I did discover that the way to get the rect's coordinates to match the screen no matter what resolution was not using global coordinates, but using the camera's coordinates, and placing code in Update() such that the rect's coordinates were updated:
timeBarRect.x = cam.pixelWidth / timerWidth;
timeBarRect.y = cam.pixelHeight / timerHeight;

Jump animation using animation class

I need a little help in my little 2D game I want to create in XNA. I had almost no knowledge of programming before I got interested in XNA and C#, so maybe my problem is simple, but I just can't figure it out.
So basically, I have a base class, and I created an additional class Animation for animating sprites. I implemented some methods so that when the player presses "right" it would change the animation's current texture and increment X by a number of xf; anyway, the main idea is that I'm using just one instance of my class (basically, one object of type animation which changes its texture and properties based on what key is pressed).
So, I had no problems making it run right or left. Works out pretty well. The big problem started when I wanted to implement the jump sprite. So I created the 6 frames necessary for the sprite, but to animate it I have virtually no idea how to do it.
The only thing it does right now is to loop through the frames of the sprite, but the position (both .X and .Y) remain the same. The thing is, I have a Vector2 position which holds the animation's current position, and it's fine with running because I simply increment it. However, when it comes to jumping, I want it to increment .X, but the .Y should be decremented (thus going up) until frame number 3; after frame number 3, until the last frame, I want the .Y position to go down (thus fall) with the corresponding animations (erm, frames).
So, basically, I don't know how to modify the .X and .Y so that it would display the frames that I need in the time I need. I don't know if you really understood what I'm trying to say; basically when I press the "up" key, it loops through the frames but the position remains the same.
My idea was to use a reference to the actual Vector2 position which holds the animation's current position and pass it to the method in the other Animation.cs class, namely the PlayAnimJump, and modify the position after each frame and return it to the actual Game1.cs by reference. Even if I would do that (though I fail to see what good it would be), it wouldn't be updating the position as it should. So, any ideas?
Here is the code for the PlayAnimJump method from the Animation class:
public void PlayAnimJump(GameTime gameTime)
{
elapsed += (float)gameTime.ElapsedGameTime.Seconds;
sourceRect = new Rectangle(currentFrame * frameWidth, 0, frameWidth, frameHeight);
currentFrame = 0;
if (elapsed >= frameTime)
{
if (currentFrame <=3)
{
if (looping)
{
currentFrame++;
}
}
else if (currentFrame > 3)
{
currentFrame++;
}
elapsed = 0;
}
}
The default constructor for that class:
public Animation(ContentManager Content,string asset,float frameSpeed, int numbOfFrames, bool looping,Vector2 positionIT)
{
this.assetName = asset;
this.frameTime = frameSpeed;
this.numbOfFrames = numbOfFrames;
this.looping = looping;
this.animation = Content.Load<Texture2D>(asset);
frameWidth=(animation.Width / numbOfFrames);
frameHeight=animation.Height;
position = positionIT;
}
Here is the code (from the main) when the up key is pressed:
else if (up)
{
check = animation1.GetAsset();
if (check == "eright")
{
animation1.SetFrameSpeed(0.8f);
animation1.SetNumbOfFrames(6);
animation1.ChangeTexture(Content, "SarimCumVreJiorjica");
animation1.PlayAnimJump(gameTime);
/*position1.x +=2f;
position1.Y -=2f;
*/
}
So, I'm not sure how, but I'm supposed to change position1 according to the frame that's displayed by the animation in that second. Am I missing something?
If your animation class had a reference to the object that you wanted to move (i.e the object holding the position field) then you could modify it within the animation class, within the PlayAnimJump method.
Or, to reduce coupling, you could just have PlayAnimJump return a variable indicating how far into the jump you are (maybe a percentage of the jump, from 0 to 1). Then, you could use the percentage outside to set the objects position. So, if the jump is halfway done, the return value would be 0.5f, which you could use in an equation to determine the players y position. An example equation would be:
float percent = animation1.PlayAnimJump(gameTime);
float y = Math.Sin(percent * Math.PI) * maxJumpHeight;
player.positon.y = y;
This uses a sine wave to determine the players height throughout the jump animation. You would just need to write the code that determines the percentage of the way through the jump (currentFrame) in the PlayAnimJump method and return it.
Formula of the frуefall for Y coordinate is
y = g * t ^ 2 / 2 + v0 * t + y0
Characters jump from height y0 vith start velocity v0 by Y axis and gravity gradually slows down and starts to fall.
Calculate deltaY using following formula
deltaY = g * t ^ 2 / 2 + v0 * t
First show the frame on which the character is pushed off the ground, then the frame on which it rises until it reaches the peak of the jump. Once the sign change deltaY from + to - show how the character change pose for fall. Something like that.

Animated Title (Like Terraria's Game Title)

What i want to do is make a title like Terraria just the rocking back and forth side of it not the graphics side i know that its just a .png rocking back and forth but could anyone help me and other people who read this and what to know how to do it?
So what i would like is to learn how to make a rocking back and forth image like the title displayed in Terraria?
Something like this for the people who don't know what Terraria is.
http://www.youtube.com/watch?v=3K8PMG42l3M
It appears that the logo is rotating and changing its size over non-equal intervals of time.
First, you need to get familiar with this method:
SpriteBatch.Draw Method (Texture2D, Vector2, Nullable, Color, Single, Vector2, Single, SpriteEffects, Single)
The parameters are:
Texture2D texture, // texture of your logo
Vector2 position, // where to draw
Nullable<Rectangle> sourceRectangle, // null
Color color, // Color.White
float rotation, // you will be changing this
Vector2 origin, // and this
float scale, // also this
SpriteEffects effects, // SpriteEffects.None
float layerDepth // 0
Use these variables:
float rotation = 0,
rotationSpeed = 0.002f, // this is how much rotation will change each frame
maximumAngle = 0.1f,
minimumAngle = -0.1f,
rotationDirection = 1,
scale = 1f, // 1 means 100%, 0.95f = 95%
scaleChange = 0.005f, // this may seem not much, but it's enough
maxScale = 1.1f,
minScale = 0.9f,
scaleDirection = 1;
Just put DrawLogo(); in your main Draw() method.
void DrawLogo()
{
// these two very similar pieces of code will control scale and rotation
if (rotationDirection > 0)
{
if (rotation < maximumAngle)
rotation += rotationSpeed;
else
rotationDirection = -rotationDirection;
}
else
if (rotation > minimumAngle)
rotation -= rotationSpeed;
else
rotationDirection = -rotationDirection;
if (scaleDirection > 0)
{
if (scale < maxScale)
scale += scaleChange;
else
scaleDirection = -scaleDirection;
}
else
if (scale > minScale)
scale -= scaleChange;
else
scaleDirection = -scaleDirection;
Texture2d t2d = logoTexture;
spriteBatch.Draw(t2d,
centerScreen, // change this to `new Vector2(123, 456)`
null, // null means draw entire texture
Color.White, // no tinting
rotation, // the rotation we calculate above
new Vector2(t2d.Width / 2, t2d.Height / 2),
// this sets rotation point to the center of the texture
scale, // the scale we calculate above
SpriteEffects.None, // you can mirror your texture with this
0); // I usually leave it zero :p
}
This is tested and works just fine :)
You mean the effect we can see at about 1:16 (and probably also at other times), when you choose stuff in the menus?
Concept
As far as I can see, you can do this with simple rotations and scaling. So, if you do not want to make an animated gif (which you suppose it is), you can just do it inside your XNA code. Take a png or gif with alpha-channel (so that the non-text is transparent).
Then, when you draw it on the screen with spriteBatch.draw() you can choose one of the overloads that support scaling and rotation.
Then you have to set:
the rotation you want to have (which will be a rotation over time)
the origin (to the center of the image)
the scale (which will be scaling over time)
As the clock is sent to the update() method as far as I remember XNA, we will have to update the rotation and scale of the image there. We need the clock, because we cannot just set rotaton = 10° and XNA will handle everything for us. We have to calculate the current rotation in each time step ourselves. E.g. if a full rotation shall endure 10 seconds and 5 seconds have passed, then you know you have a half rotation. So we would tell XNA: Set our rotation to 180° now, and in the next time step, we might tell: Set our rotation to 190° now.
The basic concept is:
Calculate how much part of rotation/scale we have done in the current time step
Tell XNA to adjust this rotation/scale in this time step
Iterate these two steps again and again
Implementation
I think the best thing to do here, is using a sin() or cos() function for the scaling and rotation. The good things about them:
they have positive and negative values as well (so we can easily rotate in both directions)
they are smooth, meaning your rotation and scaling will not look too abrupt at the end of the rotation/scaling
I hope my maths is correct here. I will explain everything, so others can correct me if something is wrong. Or also you can find out, if something is wrong. We will use a sin() here, because it starts at 0, which in our case means that nothing should happen. That’s what we want: We want to begin at a situation where nothing happens.
Now, sin() has a cycle time of 2*PI. Of course, we do not want a scaling to last 2*PI, but rather something like 1000 milliseconds. We cannot change the definition of Math.Sin() in C#, but we can change the value we throw inside. So when we mean 1000 milliseconds, we will give Math.Sin() 2PI and when we mean 500 milliseconds, we give it PI.
We would define these member variables:
// define some variables for rotation and scale speed, in milliseconds
int fullRotationTime = 1000; // max rotation will be reached after 1 second
float maxRotationAngle = MathHelper.ToRadians(10); // we will rotate by 10 degree up and down
int rotationTimePassed = 0;
float currentRotationAngle = 0;
int fullScaleTime = 1000; // max scale will be reached after 1 second
float maxScaleSize = 1.2f; // we will scale to 20% larger max
int scaleTimePassed = 0;
float currentScaleFactor = 1.0;
And in the Update() method, we calculate how much of our rotation we already have done.
protected virtual void Update(GameTime gameTime)
{
int milliseconds = gameTime.ElapsedGameTime.TotalMilliseconds;
// these are the milliseconds in the current rotation
rotationTimePassed += milliseconds;
scaleTimePassed += milliseconds;
if (rotationTimePassed >= fullRotationTime)
rotationTimePassed %= fullRotationTime;
if (scaleTimePassed >= fullScaleTime)
scaleTimePassed %= fullScaleTime;
float rotationTimeAdjustedToTwoPi = ((float)rotationTimePassed)/fullRotationTime * 2* Math.PI);
currentRotationAngle = maxRotationAngle * Math.Sin(rotationTimeAdjustedToTwoPi);
// we do not want the scaling to be negative, thus we add 1 to the whole and
// divide by 2. Then the maximum will be 1 and the minimum 0
float scaleTimeAdjustedToTwoPi = ((float)scaleTimePassed)/fullScaleTime * 2* Math.PI);
currentScaleFactor = maxScaleSize * (Math.Sin(scaleTimeAdjustedToTwoPi) + 1)/2;
}
Then, in the Draw() method we can take the values calculated before and display our rotated and scaled image.
protected virtual void Draw()
{
spriteBatch.Begin();
spriteBatch.Draw(texture,
new Vector2(50, 50),
null,
Color.White,
currentRotationAngle,
new Vector2(texture.width/2, texture.height/2),
currentScaleFactor,
SpriteEffects.None,
0
);
spriteBatch.End();
}
It’s not tested, so there might even be syntax errors, but I at least the basic idea should be correct and I think the important thing is that you understand how it can be done conceptually.
Variable time steps
It’s easy to integrate the variable time steps user1306322 has mentioned into the code above. We had these if-conditions where we checked if the current time-slice is over, like this: if (rotationTimePassed >= fullRotationTime).
Now it we want to make the time-slices variable length, just adjust a new time-slice based on a random number here. Like this:
var rand = new Random();
if (rotationTimePassed >= fullRotationTime)
{
rotationTimePassed %= fullRotationTime;
// next rotation might take between 0.5 and 2.5 seconds
fullRotationTime = rand.next(500, 2500);
}

Categories