Prevent Diagonal movements - unity3d

I'm developing a 3D tactical RPG game and I would like to know how I could prevent diagonal movements when the NPC moves? I want him to detect where the human player is in the grid and then go after him.
I can take their grid position but it didn't work. The NPC makes diagonal movements and starts to "sink" in the grid.I've tried something like this, target position is a vector 3 and I call the function in Update(), this script is attached to the NPC:
public void MoveNPC()
{
HumanPlayer = GameObject.FindGameObjectWithTag("Player");
ScriptPlayer PlayerPosition = HumanPlayer.GetComponent<ScriptPlayer>();
NPC NPCPosition = this.GetComponent<NPC>();
if ((PlayerPosition.GridPosition.x - NPCPosition.GridPositonNPC.x) + PlayerPosition.GridPosition.y - NPCPosition.GridPositonNPC.y) >= movMax &&
(PlayerPosition.GridPosition.x -NPCPosition.GridPositonNPC.x) + (PlayerPosition.GridPosition.y - NPCPosition.GridPositonNPC.y) <= movMax)
{
if((PlayerPosition.GridPosition.x - NPCPosition.GridPositonNPC.x) - (PlayerPosition.GridPosition.y - NPCPosition.GridPositonNPC.y) >= movMax &&
(PlayerPosition.GridPosition.x - NPCPosition.GridPositonNPC.x) - (PlayerPosition.GridPosition.y - NPCPosition.GridPositonNPC.y) <= movMax){
targetPosition = HumanPlayer.transform.position;
targetPosition.y = 1.4f;
}
}
if(this.transform.position != targetPosition)
{
this.transform.position = Vector3.MoveTowards(transform.position, targetPosition, velocity * Time.deltaTime);
}
}
How could I solve it?

Related

Finding angle of swipe in Unity3D

I need to find the angle between the swipe in Unity3D. In the update function I'm using the following code:
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
fingerup=Input.mousePosition;
fingerdown=Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
fingerdown=Input.mousePosition;
CheckSwipe();
}
}
and in the CheckSwipe function I'm doing this:
CheckSwipe()
{
var directionvector = fingerup-fingerdown;
if(directionvector.magnitude>SwipeThreshold)
{
/* I need to find the angle between the fingerup and the fingerdown vectors and based on that angle I need to check if the user swiped left, right, up or down. */
/*if (angle>= 45 && angle< 135) onSwipeUp.Invoke();
else if (angle>= 135 && angle < 225) onSwipeRight.Invoke();
else if (angle>= 225 && angle< 315) onSwipeDown.Invoke();
else if (angle>= 315 && angle< 360 || angle >= 0 && angle< 45) onSwipeLeft.Invoke();*/
}
}
How can I get the angle of swipe? I tried various solutions, but it was not working. Any help from any one is appreciated. Thanks in advance.
First thing, during button mouse up event, you should assign value to fingerup variable, not down.
If this doesn't fix your issue, I came up with idea to use trigonometry to calculate the angle:
if (Input.GetMouseButtonDown(0))
{
fingerup = Input.mousePosition;
fingerdown = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
fingerup = Input.mousePosition;
double angle = Mathf.Atan((fingerup.x - fingerdown.x) / (fingerup.y - fingerdown.y)) * Mathf.Rad2Deg;
if (fingerup.y < fingerdown.y) angle += 180;
if (fingerup.y > fingerdown.y && fingerup.x < fingerdown.x) angle += 360;
Debug.Log("fingerDownPos : " + fingerdown + " fingerUpPos: " + fingerup + " angle: " + angle);
}
Probably it can be written better, but I had no other idea but to use ifs and add angles depending on start and end. Anyway, it's working, and should be a good start.
Edit: your question is about an angle, but I just realized, that since you need only the general direction of a swipe (left, right, up, down) you don't need to calculate angle. Just substract fingerup.x - fingerdown.x and fingerup.y - fingerdown.y Compare which absolute value of this is bigger. If abs from vertical is bigger than horizontal, then it will be either up or down, up if the substraction is greater than 0. You get the idea how to do the rest.

OnCollisionEnter2D executing before Start on prefab

I know my code is ugly, I welcome any improvement suggestions. My goal seems simple, spawn 75 "bubbles" (prefabs) on the screen in random positions at random rotations, and have them move with a random velocity between 0.3 and 0.7, or -0.3 and -0.7. When they collide with a wall, calculate a new random velocity of the same range with respect to which wall it hit.
Currently how I am doing this:
GameManager object has a script that instantiates the bubbles
Bubble prefab has a script that sets the velocity.
How I IMAGINED it going: When the prefab script executes, the start routine would determine an initial random velocity. Then, the OnCollisionEnter2D would be called when the bubble hits a wall and it would recalculate a velocity going in whatever opposite direction the wall is (if it hits the bottom wall, set velocity to a random positive Y value, if it hits the right wall, set velocity to a random negative X value, etc).
How it is ACTUALLY going: Debug logs show the OnCollisionEnter2D executing before Start. This is causing bubbles to get "stuck" in the corner of the screen, and other unexpected behavior. See images of Bubble #70 it is stuck in the bottom left corner with the Rigidbody showing a velocity of 0,0. Debug Log shows the velocity was first calculated in the collision routine, then last calculated in the Start method as -0.7, -0.7. Obviously being stuck in the bottom left, it can't go any lower so it froze it to 0,0. This wouldn't have happened if Start had run first and THEN the OnCollisionEnter2D because the collision routine would have detected the bottom walls and set the velocity to a positive value. Now that it's stuck, it can't collide again.
I'm not sure what to do, I can put something in Start to check the position first, but I feel like I have a bigger problem with my code running the OnCollisionEnter2D before Start, and that would only be a bandaid.
GameManager script to instantiate bubble prefab:
void Start()
{
buffer = 10f;
objectCount = 75;
for (int loop = 0; loop < objectCount; loop ++){
worldMin = Camera.main.ScreenToWorldPoint(new Vector2(buffer, buffer));
worldMax = Camera.main.ScreenToWorldPoint(new Vector2(Screen.width - buffer, Screen.height - buffer));
spawnPosition = new Vector2(
Random.Range(worldMin.x, worldMax.x),
Random.Range(worldMin.y, worldMax.y));
GameObject newGO = (GameObject)Instantiate (objectToSpawn, spawnPosition, Quaternion.Euler(new Vector3(0, 0, Random.Range(-40.0f, 40.0f))));
newGO.name = newGO.name + loop;
}
Bubble prefab script to set velocity (my reason for the if statements are because if the velocity random value is very close to 0 the object moves TOO slow):
void Start()
{
Physics2D.IgnoreLayerCollision(gameObject.layer, gameObject.layer);
min = -0.8f;
max = 0.8f;
compareMax = max - 0.5f;
compareMin = min + 0.5f;
moveX = Random.Range(min, max);
moveY = Random.Range(min, max);
if (moveX < 0.0f && moveX > compareMin){
moveX = min;
}
if (moveX > 0.0f && moveX < compareMax){
moveX = max;
}
if (moveY < 0.0f && moveY > compareMin){
moveY = min;
}
if (moveY > 0.0f && moveY < compareMax){
moveY = max;
}
Debug.Log("Start name: " + gameObject.name + ", moveX: " + moveX + ", moveY: " + moveY);
rb = GetComponent<Rigidbody2D>();
rb.velocity = new Vector2(moveX, moveY);
}
void OnCollisionEnter2D(Collision2D col){
rb = GetComponent<Rigidbody2D>();
if (col.gameObject.tag == "Border"){
min = -0.8f;
max = 0.8f;
compareMax = max - 0.5f;
compareMin = min + 0.5f;
moveY = Random.Range(min, max);
moveX = Random.Range(min, max);
if (col.gameObject.name == "BottomWall"){
moveY = Random.Range(compareMax, max);
}
if (col.gameObject.name == "TopWall"){
moveY = Random.Range(min, compareMin);
}
if (col.gameObject.name == "LeftWall"){
moveX = Random.Range(compareMax, max);
}
if (col.gameObject.name == "RightWall"){
moveX = Random.Range(min, compareMin);
}
Debug.Log("OnCollision name: " + gameObject.name + ", moveX: " + moveX + ", moveY: " + moveY);
rb.velocity = new Vector2(moveX, moveY);
}

Move object with finger on x-axis 3d

I have a question: How can I moce a object on the x-axis with my finger on th smartphone? In the internet I can only find solutions for 2d but non for 3d projects.
I have tried this code, but it is really jerky:
void FixedUpdate()
{
if (Input.touchCount == 1) {
touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Moved) {
transform.position = new Vector3(
transform.position.x + touch.deltaPosition.x * speedModifier,
transform.position.y,
transform.position.z
);
}
}
transform.position = new Vector3(
transform.position.x,
transform.position.y,
transform.position.z + (speed * Time.fixedDeltaTime)
);
}
The real question is, how can I make this code, that it works smoothly, because it is really unsmoothly at the moment?
If you want to move the player where you are pressing you can use this code that is simpler than yours:
if (Input.touchCount > 0)
{
touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Moved)
{
transform.position = new Vector3(
transform.position.x,
transform.position.y,
transform.position.z + touch.deltaPosition.x * speed);
}
}
It is very customizable, in this case, for example, I am moving the player along the z-axis , like in your example, but it depends on the position of the finger from left to right.
You can easily change the last part of the code in the way you prefer, for example:
transform.position = new Vector3(
transform.position.x + touch.deltaPosition.x * speed,
transform.position.y + touch.deltaPosition.y * speed,
transform.position.z);
In this way, it will go up and down and left and right, based on the point you press and it could be useful for a game in 2d view. In 3D keep in mind that if you press up you want to move on the z axis most of the time so my first code is working well because I am changing z position on the x touch.

Unity - following finger only works for one direction

I have made some code that should make my player move into the direction of the finger:
if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Moved)
{
Vector2 pos = Camera.main.ScreenToWorldPoint(new Vector3(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y, 0));
if (pos.x < rb.position.x)
{
movehorizontal = -1;
}
if(pos.x > rb.position.x)
{
movehorizontal = 1;
}
if (pos.y < rb.position.z)
{
movevertical = -1;
}
if(pos.y > rb.position.z)
{
movevertical = 1;
}
}
Vector3 movement = new Vector3(movehorizontal, 0.00f, movevertical)*speed;
It's a 3D game, with a top-view, so my player starts at 0,0,0 and only moves along the x and z axis. My camera is positionated on 0,10,3. The following works on the x axis, so when my finger touches on the right side it goes to the right, if on the left to the left, but no matter where I touch it, it will only move to the front and not to the bottom of my screen.
I tried debugging, but the instructions werent working at the time.
screentoWorldPoint should be stored as a vector3. also since the camera is 10 units away from your plane the last parameter should be 10.
edit, that will only work for a cam pointing straight down. this code should work regardless of the camera angle.
Vector3 pos = Camera.main.ScreenToWorldPoint(new Vector3(Input.GetTouch(0).position.x, Input.GetTouch(0).position.y, 1f));
Vector3 pointDelta = pos - Camera.main.transform.position;
float multiplier = -Camera.main.transform.position.y / pointDelta.y;
pos = Camera.main.transform.position + pointDelta * multiplier;
finally these lines should compare the z values to each other
if (pos.z < rb.position.z)
if(pos.z > rb.position.z)
make those changes and let us know if any other problems still exist

Tilt Control Similar to Temple run

I want to create tilt effect just like temple run.I have a character controller(player) in the game that is moving on its forward by controller.Move(transform.forward) after which I am apply tilt to it to lean it left and right .Previously for the tilt I tried modifying the player position by using transform.translate /tranform.position directly through the accelerometer readings like this :
mytransform.translate(acceleration.x*Time.delaTime*5.0f);
but that had a problem that when I shake the device my camera starts to jerk and the player also then I used the following code to create tilt on positive Z axis
Vector3 dir = new Vector3(accel.x*8f, 0,0);
if (dir.sqrMagnitude > 1)
{
dir.Normalize();
}
dir.x = Mathf.Round(dir.x * 10f) / 10f;
//mytemp is used for temp storage of player position added with the acceleration
mytemp = mytransform.position+(mytransform.right*dir.x*Time.deltaTime*5.0f);
Vector3 diffVec=Vector3.zero;
///position of the element on which the player is colliding;
Vector3 col_pos=Collidingelement.transform.position;
Vector3 unitvec=new Vector3(1,0,0);
//removing x and z of the collider
diffVec= Vector3.Scale(col_pos,unitvec);
//nullify the y,z of the updated mytransform position so that the distance is only measured on X
Vector3 ppos = Vector3.Scale(mytemp,unitvec);
//calculate the distance between player & colliding element
disti=Vector3.Distance( ppos,diffVec);
disti=Mathf.Clamp(disti,-1.5f,1.5f);
disti = Mathf.Round(disti * 10f) / 10f;
//update the player position and apply tilt to it if the distance is less than 1.5f
if(disti<=1.50f)
{
mytransform.position=mytemp;
}
now this has a problem that if lets say I have a value of 0.1 in the acceleration its keep on update my temp and if the distance is less my player will start leaning towards a side though I held my device on same position and acceleration value was always 0.1
Why don't you just calculate delta acceleration.
bool isMoved = false;
Vector2 lastAccel = Vector2.Zero;
Vector2 margin = new Vector2(0.05f, 0.05f); //not processing if its in margin.
Vector2 deltaAccel = currAccel - lastAccel ;
if(deltaAccel.x < margin.x)
{
//don't process
isMove = false;
}
else
{
isMove = true;
lastAccel = currAccel;
}
if(isMove)
{
//Process with deltaAccel here
}