I have a player sprite and a spikes sprite. The spikes are facing down and about at head level with the player. I have set it so that if the right side of the player's rectangle goes into the spikes's rectangle, it stops moving. However, I want to set it up like this-
if (playerRect.Right == spikesRect.Left - 1)
{
speedRight = 0;
}
However, this does not work. The player can continue to go past it. The only way I can get it to work is if I do this-
if (playerRect.Right > spikesRect.Left)
{
speedRight = 0;
}
To clarify, the spikesRect.Left value is 350. I want it so that if playerRect.Right is equal to 349, to stop moving to the right. Thanks for any help, it's appreciated.
If you just want a basic collision, use:
if(playerRect.Intersects(spikesRect))
{
//handle collision
}
I recommend having a velocity and a direction variable instead of different variables for different direction's speeds, it means that you only have to change one variable if you want your character to change speed or direction.
The main problem is is that as your player is moving it is not always going to land on spot 349. as its moving it might move from 348 to 350. therefore it will never trigger when it's 349. What you could however do is.
int i = spikesRect.Left - playerRect.Right;
if ( i < 0 )
playerRect.X += i; //playerRect.X can be replaced by a position variable
When it reaches spot 351. 350 - 351 = -1 so since it is less than 0 it will be added to playerRect.X making playerRect.X moved back to where playerRect.Right is 350. That way it won't look as if your player is penetrating the spike.
I think that the issue is caused by some changes you make to speedRight or to playerRect somewhere in your game. So if you're using VisualStudio just set a breakpoint and check the speedRight and playerRect values.
Although there are a few changes you should make to your game. Firstly you should create a public field into the Player class of type Texture as for the Spike class, then create another field of type Vector2 which indicates the speed and the direction :
public class Player{
public Vector2 DirectionSpeed;
public Texture2D Texture;
//...
public Player(){
//initialize your fields
}
}
Then you can handle the collision by using the method Intersects():
if(player.Texture.Bounds.Intersects(spike.Bounds)){
player.DirectionSpeed = Vector.Zero;
}
If you are trying to handle the collisions with more than one object of type Spike, you have to create a List<Spike> and then iterate with a cicle the entire list:
foreach(Spike s in listSpikes){
if(player.Texture.Bounds.Intersects(s.Bounds)){
player.DirectionSpeed = Vector.Zero;
}
}
EDIT:
Moreover if speedRight doesn't equal 1 or a submultiple of spikesRect.Left - 1 it's obvious that by increasing the position with it playerRect.Right exceeds spikesRect.Left - 1. A solution could be:
if (playerRect.Right > spikesRect.Left - 1)
{
playerRect.Location = spikesRect.Left - playerRect.Width - 1;
speedRight = 0;
}
Related
mono script:
using BezierSolution;
using System.Collections;
using System.Collections.Generic;
using UnityEditor.TerrainTools;
using UnityEngine;
public class RandomBezierSpline : MonoBehaviour
{
[Header("Bezier Spline")]
[Range(2f, 100f)]
public int numberOfBeziers = 2;
public bool randomNumberOfBeziers = false;
public BezierSpline bezierSpline;
private int oldNumberOfBeziers;
public void GenerateBezier()
{
if (oldNumberOfBeziers != numberOfBeziers)
{
bezierSpline.Initialize(numberOfBeziers);
oldNumberOfBeziers = numberOfBeziers;
}
}
}
editor script:
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.TerrainTools;
using UnityEngine;
[CustomEditor(typeof(RandomBezierSpline))]
public class RandomBezierSplineEditor :Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
RandomBezierSpline randomBezierSpline = (RandomBezierSpline)target;
randomBezierSpline.GenerateBezier();
}
}
the part of another script that creating the objects:
public void Initialize( int endPointsCount )
{
if (endPointsCount <= 2)
{
return;
}
// Destroy current end points
endPoints.Clear();
GetComponentsInChildren( endPoints );
for( int i = endPoints.Count - 1; i >= 0; i-- )
DestroyImmediate( endPoints[i].gameObject );
// Create new end points
endPoints.Clear();
for( int i = 0; i < endPointsCount; i++ )
InsertNewPointAt( i );
Refresh();
}
The problem is when i move the Range slider in the inspector to the right increasing the value it's creating new Point's objects. but then when i slide the Range slider to the left decreasing the value it's destroying the Point's but when the slider is at value 0 there are still Point's left sometimes 2 sometimes 4 sometimes more or less but it's never destroyed all the Point's objects when getting to the value 0.
Update :
i tested it again and it seems like when I'm sliding the Range slider too fast to the left side it can't handle it and can't destroy all the Point's objects. the fastest I'm moving the Range slider the more Point's left. if i move the slider very slow the best i can get is left with 3 Point's but it should be 2 the minimum of Point's is 2.
is there a way to work around this slider moving speed problem?
here is a screenshot after i moved the Range slider to the right and the value is 17 there are 17 created Point objects :
now depending on the speed i drag and move the slider to the left side how much point object will be left in the hierarchy :
in this case i moved the slider very fast and the slider value is 2 but in the hierarchy there are 14 point objects. because i moved the slider so fast it couldn't handle and destroy all the point objects so the vlaue is 2 but there are 14 objects :
and this screenshot is when i moved the slider very very slow to the left i moved it one by one and the value is 2 but there are 3 point objects left :
what i want to do is when i move the slider to the right create Point object depending on the value it is currently. but if i keep moving it to the right add the amount of needed objects for example i moved to the right and stopped at value 7 then i moved it again from 7 to 14 then it should create more 7 objects to the already existing 7 and not create 14 new ones.
same if i'm moving it to the left to remove objects same logic and to solve also the speed problem.
If you call add/remove points when the slider value changes, you should get the difference between old slider value and the new one. This is the number of points you want to add/delete.
Moving slider too fast can skip some values.
I assume you don't want to loose the Points already in the scene, so generating them every time from scratch is not an option.
I have a colliding object which can come from any direction, and I would like to check the position relative to the center of a sphere.
My idea was to create a vector with the same direction as the arrow that went through the center of the sphere and then check if the arrow position is over or under the new vector, but I don't know how to achieve this.
In general a Vector has no position. It is only a direction and magnitude in space. A position basically is a vector itself that points from the world origin (0,0,0) to the according position. So if you only have a directional vector it contains no information whatsoever about the position.
You would need to define top and bottom better but if you just want to check in global space you can simply check whether the collision contact point is above or below the sphere center by comparing their Y axis value.
Something like e.g.
// Assuming this script is on the Sphere
private void OnCollisionEnter(Collision collision)
{
// You could of course take all contact points into account and take an average etc
// but to keep things simple just use only one for now
var contact = collision.GetContact(0);
var contactPoint = contact.point;
var ownCenter = contact.thisCollider.bounds.center;
if(contactPoint.y > ownCenter.y)
{
Debug.Log("Hit on top half");
}
else
{
Debug.Log("Hit on bottom half");
}
}
If you rather want to check the local space (e.g. because your sphere is rotated like in your graphic) you can use almost the same but simply convert the positions into local space first
var contactPoint = transform.InverseTransformPoint(contact.point);
// In the case for a sphere this should most probably be equal to simply using 0,0,0
// In case of a "SphereCollider" you could also use that specific type and then use "sphereCollider.center" which already is in local space
// But to have it working generally keep using the center for now
var ownCenter = transform.InverseTransformPoint(contact.thisCollider.bounds.center);
You can get the point of impact. You can then measure the distance from the top and bottom of the sphere to the point of impact. The smaller distance is always the one it is closer to.
void OnCollisionEnter(Collision col)
{
var top = transform.position + transform.localscale.y/2 * transform.up;
var bottom = transform.position + transform.localscale.y/2 * -transform.up;
var isTop = Vector3.Distance(top, collision.point) < Vector3.Distance(bottom, collision.point);
if (isTop) {
// It hit the top
} else {
// It hit the bottom
}
}
I`m making a 2d game based on levels in which, each level, you have three checkpoints in the score tracking bar. The player must reach the lowest checkpoint to be able to pass to the next level, but will get a bonus if he reaches the 2nd and 3rd checkpoints.
I tought on using a Slider as the scoring bar. My question is:
Is there a way to store a specific value of the Slider's bar in the Start method and Instantiate a marker prefab at that position? Here's an example:
The Max Value of the Slider at Level 1 is 100.
I want to Instantiate the first marker, with some padding in the y, in the 50`s position of the slider, the second in the 75 position and the third in the 100 position.
My current logic is that I need to, somehow, get the value I want and find his Transform, but I can`t find a way to code this, I have no idea how to get the position I want.
Here are some images to illustrate what i`m trying to do:
i would get the width attribute of the slider, then divide that by sliderMax, the result will be the the width of a single % on the slider. you can then add or subract multiple of this to get a percentages place on the bar.
example: slider.x=50
slider.width=200;
increment = slider.width/100; //this will result in two, giving you two pixels per percent.
so your 50 percent placement would be: sliderx+(increment*50);
keep in mind this is all pseudo code, designed to give you an idea of how to acheive your desired result
I found the solution!
Based on the insights i managed to do this:
void SpawnCheckPoint() {
mySlider.maxValue = gameLevel[currentLevel].maxValue; //Set the slider's Max Value to the max value of the level.
float sliderMaxValue = mySlider.maxValue;
float sliderWidth = slider.GetComponent<RectTransform>().sizeDelta.x; //Get the width of the Slider.
float zeroValue = slider.transform.position.x - (sliderWidth / 2); //Get the leftmost corner of the slider.
//Loop to Instantiate the 3 checkpoints.
for (int i = 0; i < gameLevel[currentLevel].values.Length; i++) {
float valueToIncrement = (gameLevel[currentLevel].values[i] / sliderMaxValue); //Get the % of the checkpoint based on the max value of the level.
float newPos = (sliderWidth * valueToIncrement); //New position in screen
//Instantiate the object as a child of the Slider
GameObject checkpoint = Instantiate(checkPoint, new Vector3(zeroValue + newPos - xPadding, slider.transform.position.y - yPadding, slider.transform.position.z),
Quaternion.identity, GameObject.FindGameObjectWithTag("Slider").transform);
}
}
It's probably not the best way to do what i want but it's working just fine.
Thank you all who tried to help me, your insights were very useful.
I have a button that makes the MainCamera switch between being in the middle of several objects.
For example, there's the [StartPoint , CheckPoint , CheckPoint , EndPoint]
I want the camera to switch continuously across the checkpoints like the comma between the checkpoints. ^^
This code is the actual switching the position placing for the MainCamera (where the error might be)
public void SwitchCameraBetween(GameObject nextPoint, GameObject afterNextPoint)
{
Vector3 centerPoint = (afterNextPoint.transform.position - nextPoint.transform.position) / 2;
centerPoint.z = -10;
float cameraSize = (afterNextPoint.transform.position - nextPoint.transform.position).magnitude - nextPoint.transform.localScale.x;
mainCamera.transform.position = centerPoint;
mainCamera.orthographicSize = cameraSize / 3;
}
The camera switches perfect for the first 2 checkpoints (either StartPoint & EndPoint or StartPoint & CheckPoint) after the camera stays in same position or off by a couple values. I checked by using Debug.Log(); to see if the camera has the correct gameobjects between and it does so why does it not work?
The center point should be the average of all points, so you need to add your points, not subtract them, and then divide the result by the number of points included for the average.
center = sum(points) / count(points), so center = (a + b) / 2
Alternatively, you could use Vector3.Lerp(a, b, 0.5f) if you find that more readable, although technically this would be slower, since it's both a method call and more operations, unless the compiler is doing fancy things behind the scenes...
I'm trying to move a PictureBox diagonally in a game I'm making.
private void movebulletupright()
{
//this part is mainly for checking the action[![enter image description here][1]][1]
for (int k = bulletlistupright.Count - 1; k >= 0; k--)
{
bulletlistupright[k].Location.X++;
bulletlistupright[k].Location.Y++;
//This part is just basically meant to get rid of the bullet
//when it reaches the end of the screen
if (bulletlistupright[k].Left >= this.ClientSize.Height)
{
this.Controls.Remove(bulletlistupright[k]);
bulletlistupright.RemoveAt(k);
}
}
}
I'm using a timer to move the bullets. What I would like to do is move the bullet 5 pixel per tick (which is 1 millisecond). if you look at the attached picture below, what i'm trying to do is move those yellow bullet shaped in the corners diagonally.(i only have them there so i can represent where they spawn in). [1]: http://i.stack.imgur.com/wQc5l.png
Try to move in one go:
bulletlistupright[k].Location = new Point(
bulletlistupright[k].Location.X + 5, // 5 is X step
bulletlistupright[k].Location.Y + 5); // 5 is Y step
in order to prevent jitting (i.e. unwanted redrawing - first redrawing after X coordinate is changed, than after Y)
I'm not sure I understand your question, but if you are moving it 1 pixel in your code, to move it 5 pixels, you'd only need to do:
bulletlistupright[k].Location.X+=5;
bulletlistupright[k].Location.Y+=5;
If that's not what you are looking for, please be more clear in your question