2d runner same spacing between different sized gameobjects - c#

my problem is keeping same spacing between different sized prefabs in randomly generated 2d runner.
i want to spawn new gameobject every second
let's say i have simple sprite called square
i am spawning it using coroutine and distance is always equal to 1s of movement
i added different sized arrays of squares as prefab and when i spawn it with 1 unit squares i would love to have same distance between prefabs as if i was spawning single squares one after another.
basically i would love to spawn different sized prefabs and spawn them at same interval by keeping same distance between different prefabs.
maybe the solution is to spawn prefabs based on measured distance between prefabs instead of spawning based on time
how would you aproach this problem?
can i calculate width of empty gameObject based on width of array of its children?
i hope you can understand what am i asking
thank you!
void Start() {
stvaranjeFunkc();
}
// Update is called once per frame
void Update() {
if (privremeniNiz.tag == "zamka")
{
if (privremeniNiz.transform.position.x + privremeniNiz.transform.localScale.x / 2 < stvarac.transform.position.x - vrijednostGranice)
stvaranjeFunkc();
}
if (privremeniNiz.tag == "nizPreprekaZamka")
{
// if ((privremeniNiz.GetComponent<nizKutija>().niz[privremeniNiz.GetComponent<nizKutija>().randomBrKutija].transform.position.x + privremeniNiz.GetComponent<nizKutija>().niz[privremeniNiz.GetComponent<nizKutija>().randomBrKutija].transform.localScale.x / 2)
//> stvarac.transform.position.x - vrijednostGranice)
if ((privremeniNiz.gameObject.GetComponent<nizKutija>().niz[0].transform.position.x + privremeniNiz.GetComponent<nizKutija>().niz[0].transform.localScale.x / 2)
> stvarac.transform.position.x - vrijednostGranice)
return;
// if (privremeniNiz.GetComponent<nizKutija>().niz[privremeniNiz.GetComponent<nizKutija>().randomBrKutija].transform.position.x + privremeniNiz.GetComponent<nizKutija>().niz[privremeniNiz.GetComponent<nizKutija>().randomBrKutija].transform.localScale.x / 2 < stvarac.transform.position.x - vrijednostGranice)
stvaranjeFunkc();
}
//if (!cekanje)
// StartCoroutine(stvaranje());
//else return;
}
void stvaranjeFunkc()
{
int poz = Random.Range(0, prepreka.Length);
GameObject temp =Instantiate(prepreka[poz], stvarac.transform.position, stvarac.transform.rotation);
privremeniNiz = temp;
}
i got it working when i have simple gameobject (tag=zamka) but when i
spawn gameobject of tag nizPreprekaZamka which is empty gameobject that has script attached which creates array of simple objects spawner just spawns hundreds of gameobjects at once

You probably know the speed that your game horizontally scrolls. I'm assuming you're tracking the position of each block and you can tell what their widths are.
The trick is to spawn the blocks off-screen so you always have enough content to scroll into view to cover the next frame.
How much content is off-screen? I'm assuming you just append new blocks to the end of the array. That means the last block is always the furthest off-screen, which helps us. It also helps to know the size of the screen. In that case, you can calculate the amount of content off-screen as last block position + its length + fixed_space - screen size, where fixed_space is the amount of space you want after each block.
Check each frame if the scroll speed > the amount of content off-screen. If so, you need to generate a new block. Your block's starting position should be exactly where the content off-screen ended.

The position of a GameObject is located at its center, while is scale is his total size.
So the edge of an object is located at its position plus half the scale:
float distance = transform.position.x + (transform.scale.x / 2f);
So for each new prefab, you want to add the distance between the center and edge of both GameObject plus the distance that should seperate them.
public GameObject[] prefabs;
public float distanceBetweenObjects;
float newPosition = prefabs[0].transform.position.x;
newPosition += (prefabs[0].transform.scale.x / 2f);
newPosition += distanceBetweenObjects;
newPosition += (prefabs[1].transform.scale.x / 2f);

Related

Calculating changing Mathf.Clamp() values for object of changing size

I've been wracking my brain over this problem for a while. I have a controllable object (only moveable up and down) that I have clamped on the top and bottom. However, every time a certain trigger is activated, the object shrinks 10% until it is 90% of the original size. The problem comes in when I shrink it. When it shrinks, the min and max values of the clamp don't change at all and this results in the object clamping to soon on the min and max. They need to decrease and increase respectively so that it clamps in the exact same place. How would one do this? I've tried so many different methods but to no avail...
This is the way I shrink my player:
playerWidth /= 1.1f;
playerHeight /= 1.1f;
Vector3 scale = new Vector3(playerWidth, playerHeight, 1f);
playerOneShrink.transform.localScale = scale;
Many Thanks!
EDIT 1:
Let me give an example using a game that might help get my point across better. Basically think flappy bird, but the player uses the up and down arrows to move and not space-bar. When the bird dies, the bird would reset but become smaller. It seems that because the bird is smaller it now moves 'less' up and down, and doesn't touch the top and bottom of the screen anymore. I want the bird to still be touching the top and bottom of the screen.
EDIT 2:
So apparently my first edit didn't clarify as much as I thought so I'm going to show my code for a test scene I'm trying this all in. I haven't shown the changing of minValue and maxValue because that's what I'm struggling with...
private static Rigidbody2D playerOneRB;
GameObject player1;
float verticalMovement = 0;
public static float playerHeight = 0.3417f;
public static float playerWidth = 0.05400001f;
public float minValue = 0;
public float maxValue = 10;
public static float p1VerticalSpeed = 3;
public GameObject playerOneShrink;
// Start is called before the first frame update
void Start()
{
playerOneRB = GameObject.FindGameObjectWithTag("P1 Normal").GetComponent<Rigidbody2D>();
player1= GameObject.Find("P1 Normal");
}
// Update is called once per frame
void Update()
{
verticalMovement = Input.GetAxis("Player 1 V"); //Looking for axis defined in our input manager
playerOneRB.velocity = new Vector3(0f, verticalMovement * p1VerticalSpeed, playerOneRB.velocity.x);
Vector3 scale1 = new Vector3(playerWidth, playerHeight, 1f);
Vector3 position = transform.position;
player1.transform.position = new Vector3(player1.transform.position.x, (Mathf.Clamp(player1.transform.position.y, minValue, maxValue)), 0f); //Restricting how far the players can move (aka, not off the screen)
if (Input.GetKeyDown(KeyCode.Alpha1))
{
playerWidth /= 1.1f;
playerHeight /= 1.1f;
scale1 = new Vector3(playerWidth, playerHeight, 1f);
paddleOneShrink.transform.localScale = scale1;
}
}
Here's a photo of what's happening:
1. Photo of position it reaches before shrinking
2. Photo of position it reaches after shrinking
I want the player in image 2 to be able to get to the same top position as in image 1 after it shrinks.
It sounds like you want to scale the object, but keep it pivoted, so if it's at the top most position, and scales, it stays at the top most position? If so, the code and answers here will help:
https://answers.unity.com/questions/14170/scaling-an-object-from-a-different-center.html
You'll of course need to add in some conditional code to check whether it's a top or bottom pivot.
Hope I understood your problem.
So let's assume the scale of the player is 1 unit and you have to clamp in y axis between 0 and 10.
so you will have to clamp the Y position of player like
Vector3 scale = new Vector3(playerWidth, playerHeight, 1f);
Vector3 position = transform.position;
position.y = mathf.clamp(0 + scale.x ,10 - scale.x ,position.y );
transform.position = position;
so if the player's scale is 1 then it will limit the y position between 1 (0+1) and 9 (10-1).
if the player's scale is 0.9 then it will be between 0.9 (0+0.9 ) and 9.1 (10-0.9)
if the scale is 3 then between 3 (0+3) and 7 (10-3)

Moving and scaling an object according to hand position

I need some help with my college project. I have a cylinder and need it to act as a coil. For example, if I touched the cylinder's surface it's height will decrease (scaled in the y direction) as if pressing on a coil then when I remove my hand it returns back to its original size.
This is what I reached till now but I still have some problems that I can't solve.
public class Deformation : MonoBehaviour
{
Vector3 tempPos;
private void InteractionManager_SourceUpdated(InteractionSourceUpdatedEventArgs hand)
{
if (hand.state.source.kind == InteractionSourceKind.Hand)
{
Vector3 handPosition;
hand.state.sourcePose.TryGetPosition(out handPosition);
float negXRange = transform.position.x - transform.localScale.x;
float posXRange = transform.position.x + transform.localScale.x;
float negYRange = transform.position.y - (transform.localScale.y / 2);
float posYRange = transform.position.y + (transform.localScale.y / 2);
float negZRange = transform.position.z - transform.localScale.z;
float posZRange = transform.position.z + transform.localScale.z;
float handX = handPosition.x;
float handY = handPosition.y;
float handZ = handPosition.z;
if ((negXRange <= handX) && (handX <= posXRange) && (negYRange <= handY) && (handY <= posYRange) && (negZRange <= handZ) && (handZ <= posZRange))
{
tempPos.y = handPosition.y;
transform.localScale = tempPos;
}
else
{
tempPos.y = 0.3f;
transform.localScale = tempPos;
}
}
}
// Use this for initialization
void Start()
{
tempPos = transform.localScale;
InteractionManager.InteractionSourceUpdated += InteractionManager_SourceUpdated;
}
I attached two scripts to my object (cylinder) the TapToPlace script from the HoloToolKit and the deformation script stated above. The problem is when I deploy to my HoloLens to test, when I place the cylinder first to the needed place then try to deform it after that, it is placed but not deformed. If I tried it the other way around both work. Any ideas why does the deformation script does not work after the TapToPlace one?
The cylinder when viewed by my HoloLens is somehow transparent. I mean that I can see my hand through it. I need it to be more solid.
I wonder if there is something like a delay that I can use because when I use the deformation script stated above the cylinder is scaled to my hand position then scaled back to its default size very fast and appears as if blinking.
At first I place the cylinder on a setup (something as a table for example) then I begin to deform it. When I commented the else part in the deformation script stated above, it was scaled and left stable without returning to the original size. It is scaled symmetrically so its height is decreased from up and down resulting in the base of the cylinder becomes away from the table. I need the base of the cylinder to be always stable and touching the table under it.
Note: I am using Unity 2017.3.1f1 (64-bit) - HoloToolkit-Unity-2017.2.1.3
Thank you in advance.
1) Did you see the MRTK 2017.2.1.4 release? It has some useful features such as two handed resizing/scaling of objects. The BoundingBox code in the new MRTK release does moving and resizing in one component, it might be a better base to start from than the TapToPlace, or at least show how the two types of transform can work together.
2) What colour is your object? Hololens will render black as transparent, so try making the object bright white for testing. Also, just double check the brightness is turned up to full (the LHS buttons on the hololens). Finally, check your shader is the MRTK Standard shader. (again, the 2017.2.1.4 release has new shader code you might want to try.) . In a room without direct sunlight it should pretty much cover up your hand.
4) I'm not sure I follow completely, but the pivot point could be important here. If it is centred in the middle of the coil (as I'd imagine it is) then when you deform the coil down it will still stay centered at that central pivot point.
If you instead set the pivot point to the bottom of the coil, touching the table, you can scale and that point stays on the table and the top does all the moving.

Unity2D C# Randomly Spawn GameObject in an Area over another GameObject

I'm new to Unity2D (Unity 5.0.2f1) and have been searching for a solution which I'm sure is staring me in the face!
I have a game object (essentially a road) like below (DirtTrack1):
I have a spawner which spawns GameObjects (vehicles). I want to spawn those vehicles over this road.
I have tried the following code to do this, essentially trying to spawn the vehicle within the Y-axis area of the road by getting the bottom Y co-ordinate of the road and the top Y co-ordinate, so I get the min and max vertical positions of where I can place the vehicle:
void FixedUpdate() {
// Repeat spawning after the period spawn
// route has finished.
if (!_inSpawningIteration)
StartCoroutine (SpawnVehiclePeriodically());
}
IEnumerator SpawnVehiclePeriodically()
{
// First, get the height of the vehicle and road.
float vehicleHeightHalf = vehiclePreFab.GetComponent<SpriteRenderer>().bounds.size.y / 2f;
float roadHeightHalf = roadObject.GetComponent<SpriteRenderer>().bounds.size.y / 2f;
float roadTopY = roadObject.transform.position.y + roadHeightHalf;
float roadBottomY = roadObject.transform.position.y - roadHeightHalf;
// Next, ensure that maxY is within bounds of this farm vehicle.
roadMaxY = roadTopY - vehicleHeightHalf;
roadMinY = roadBottomY + vehicleHeightHalf;
// Set the position and spawn.
Vector3 newPosition = new Vector3 (Const_RoadItemsPositionX, randomY, 0f);
GameObject vehicle = (GameObject)GameObject.Instantiate (vehiclePreFab, newPosition, Quaternion.identity);
}
This does spawn randomly but most times it is always not within the road itself. It is either part on the road or at the outside edge of it.
I can't figure out what I'm doing wrong here but I'm sure it is something very simple!
Tick the kinematic check of your vehicle, physics may be moving it out of the road if you don't do that.
You are using localPosition. From documentation:
Position of the transform relative to the parent transform.
If the transform has no parent, it is the same as Transform.position.
Looking at your scene, your road has a parent object and the relative position you are getting might be messing up with the spawn position of cars.

Getting distance between point of an object and another object

First, I'd like to apologize because this is a very basic and repetitive question, but I am completely new to game development.
I understand that I can find a distance between two objects using:
float dist = Vector3.Distance(other.position, transform.position);
However, how can I find the distance between a point of one object to other object?
For instance let's say my object is this sphere
Now, how can I return an array that says that there are no objects to the left (null), in the front there is an object at 1, and to the right there is an object at 0.5?
Thank you for your patience and understanding
I'm not exactly sure what you wan't to achieve...
If you wan't to get potential objects at 0.5, 1, 1.5, etc. on lets say the Z Axis you probably would want to do this with raycasting.
If you wish to check for any objects returning the direction dependant to the Z Axis (0.5, 0.856, 1.45, etc) in contrast, you probably would either
use a scaled sphere collider and add the colliding object with the OnCollisionEnter Callback to the array/List
iterate through every object of the scene and check it's relative pos
Use Raycast Probes procedurally (using a density float and Raycasting every density offset on the Z Axis and checking if the ray hit anything ...)
...
Totally dependant on your case of use, and whether you use 2D or 3D.
Seneral
EDIT: Here's what you would want in 2D to get a wall withing range maxRange on the layer optionalWallLayer in direction y 1 (up in unity 2D)
float maxRange = 10.0f;
RaycastHit hit;
Vector3 dir = transform.TransformDirection(new Vector3 (0, 1, 0));
if (Physics.Raycast(transform.position, dir, maxRange, out hit, LayerMask optionalWallLayer))
{
Debug.Log ("Wall infront of this object in Range" + hit.distance);
// hit contains every information you need about the hit
// Look into the docs for more information on these
}
This would likely go into the Update Function of your Sphere's MonoBehaviour.
The option with the Sphere collider is useful if you are not sure if you are going to hit your obstacles. If these are small, you would likely want to add the said Sphere Collider as a component to your sphere, scale it up to your maximum distance, and add a MonoBehaviour script to the sphere, which would contain something like this:
public List<Transform> allObjectsInRange; // GameObjects to enclose into calculations, basically all which ever entered the sphere collider.
public List<float> relatedDistances;
void Update () {
// basic loop to iterate through each object in range to update it's distance in the Lists IF YOU NEED...
for (int cnt = 0; cnt < allObjectsInRange.Count; cnt++) {
relatedDistances[cnt] = Vector2.Distance (transform.position, allObjectsInRange[cnt].position);
}
}
// Add new entered Colliders (Walls, entities, .. all Objects with a collider on the same layer) to the watched ones
void OnCollisionEnter (Collision col) {
allObjectsInRange.Add (col.collider.transform);
relatedDistances.Add (Vector2.Distance (transform.position, col.collider.transform));
}
// And remove them if they are no longer in reasonable range
void OnCollisionExit (Collision col) {
if (allObjectsInRange.Contains (col.collider.transform)) {
relatedDistances.RemoveAt (allObjectsInRange.IndexOf (col.collider.transform));
allObjectsInRange.Remove (col.collider.transform);
}
}
That should do it, either of the options, based on your exact case, again:) Note both are pseudo-codes... Hope it helps!

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.

Categories