i have a problem. I am making a game that can shoot some kind of spider man rope , in standalone version i'm using mouse to point the direction, something like this:
// Get Direction
public void setTarget(Vector2 targetPos)
{
Vector2 dir = targetPos - origin.position;
dir = dir.normalized;
velocity = dir * speed;
transform.position = origin.position + dir;
pull = false;
updateLine = true;
}
// Set Direction On Pc Version
if (Input.GetMouseButtonDown(1))
{
Vector2 worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
rope.setTarget(worldPos); // another script will get this value
}
And Heres the problem :
// Set Direction On Mobile (The Problem)
if (Input.GetMouseButtonDown(0))
{
Vector2 direction = new Vector2(joystick.Horizontal, joystick.Vertical);
rope.setTarget(direction);
}
and it's working fine, but now i want to make the mobile version using virtual joystick that i downloaded from the assets store, i want to get the virtual joystick angle so that the rope can shoot to that angle direciton. Please help me , sorry for my bad english, thanks
I suppose it's one of two things:
You are using your "direction" as target and it looks like rope.transform.position + direction is your target position.
rope.setTarget(rope.transform.position + direction);
You are not considering camera angle. You should rotate your distance by Camera rotation y
rope.setTarget(rope.transform.position + Quaternion.AngleAxis( Camera.main.transform.rotation.eulerAngles.y, Vector3.up ) * direction);
Related
I'm making a 3d pool game and I stuck with this problem.
I can't find the needed function to add an impulse to a ball which will make the ball to spin.
In other words, how to set the AIM point from where I want to add the impulse?
If I use AddForce or AddTorque, it seems that it calculates it from the Center of the Ball.
But how to specify the aim point (Left english, Right english, etc...)?
And how to route the ball to the camera direction after a cue hit the ball?
At first look I think you should check Rigidbody.AddForceAtPosition. You should calculate the aim points somehow in world coordinates also.
I am relatively new on Unity but the main idea came to my mind first rotate the cue vector by y axis by a small amount angle, then calculate the hit point for each regions by casting physics ray then finally apply impulse by using Rigidbody.AddForceAtPosition. I tried to write a sample code:
public class SphereController : MonoBehaviour {
private Vector3 cueStartPoint;
void Start () {
cueStartPoint = new Vector3(0, 0.5f, -13f);
}
void Update () {
//direction from cue to center
var direction = transform.position - cueStartPoint;
//rotate cue to aim right english
var angleForRightEnglish = 5f;
var directionForRight = Quaternion.AngleAxis(angleForRightEnglish, Vector3.up) * direction;
Debug.DrawRay(cueStartPoint, directionForRight, Color.red, 10f);
//rotate cue to aim right english
var angleForLeftEnglish = -5f;
var directionForLeft = Quaternion.AngleAxis(angleForLeftEnglish, Vector3.up) * direction;
Debug.DrawRay(cueStartPoint, directionForLeft, Color.blue, 10f);
//try a sample hit from right
if (Input.GetKeyDown(KeyCode.RightArrow)) {
var forceMagnitude = 1f;
var hitForce = forceMagnitude * directionForRight.normalized;
//calculate right hit point on sphere surface
RaycastHit hitInfo;
if (Physics.Raycast(cueStartPoint, directionForRight, out hitInfo)) {
var rightHitPoint = hitInfo.point;
gameObject.GetComponent<Rigidbody>().AddForceAtPosition(hitForce, rightHitPoint, ForceMode.Impulse);
}
}
//try a sample hit from left
if (Input.GetKeyDown(KeyCode.LeftArrow)) {
var forceMagnitude = 1f;
var hitForce = forceMagnitude * directionForLeft.normalized;
//calculate left hit point on sphere surface
RaycastHit hitInfo;
if (Physics.Raycast(cueStartPoint, directionForLeft, out hitInfo)) {
var leftHitPoint = hitInfo.point;
gameObject.GetComponent<Rigidbody>().AddForceAtPosition(hitForce, leftHitPoint, ForceMode.Impulse);
}
}
}
}
this script should be added to ball as component of course, hope this helps.
In my scenario, I have a table (plane) that a ball will roll around on using nothing but physics giving the illusion that the mobile device is the table using Input.gyro.attitude. Taking it one step further, I would like this relative to the device origin at the time Start() is called, so if it is not being held in front of a face or flat on the table, but just relative to where it started, and may even be reset when the ball is reset. So the question is, is how do I get the difference between the current attitude and the origin attitude, then convert the X and Z(?) difference into a Vector3 to AddForce() to my ball object whilst capping the max rotation at about 30 degrees? I've looked into a lot of Gyro based input manager scripts and nothing really helps me understand the mystery of Quaternions.
I could use the relative rotation to rotate the table itself, but then I am dealing with the problem of rotating the camera along the same rotation, but also following the ball at a relative height but now with a tilted offset.
AddForce() works well for my purposes with Input.GetAxis in the Editor, just trying to transition it to the device without using a Joystick style UI controller.
Edit: The following code is working, but I don't have the right angles/euler to give the right direction. The game is played in Landscape Left/Right only, so I should only need a pitch and yaw axis (imagine the phone flat on a table), but not roll (rotated around the camera/screen). I may eventually answer my own question through trial and error, which I am sure is what most programmers do.... XD
Started on the right track through this answer:
Answer 434096
private Gyroscope m_Gyro;
private speedForce = 3.0f;
private Rigidbody rb;
private void Start() {
m_Gyro = Input.gyro;
m_Gyro.enabled = true;
rb = GetComponent<Rigidbody>();
}
private Vector3 GetGyroForces() {
Vector3 resultantForce = Vector3.zero;
//Quaternion deviceRotation = new Quaternion(0.5f, 0.5f, -0.5f, -0.5f) * m_Gyro.attitude * new Quaternion(0,1,0,0);
float xForce = GetAngleByDeviceAxis(Vector3.up);
float zForce = GetAngleByDeviceAxis(Vector3.right);
//float zForce = diffRot.z;
resultantForce = new Vector3(xForce, 0, zForce);
return resultantForce;
}
private float GetAngleByDeviceAxis(Vector3 axis) {
Quaternion currentRotation = m_Gyro.attitude;
Quaternion eliminationOfOthers = Quaternion.Inverse(Quaternion.FromToRotation(axis, currentRotation * axis));
Vector3 filteredEuler = (eliminationOfOthers * currentRotation).eulerAngles;
float result = filteredEuler.z;
if (axis == Vector3.up) {
result = filteredEuler.y;
}
if (axis == Vector3.right) {
result = (filteredEuler.y > 90 && filteredEuler.y < 270) ? 180 - filteredEuler.x : filteredEuler.x;
}
return result;
}
void FixedUpdate() {
#if UNITY_EDITOR
rb.AddForce(new Vector3(Input.GetHorizontal * speedForce, 0, Input.GetVertical * speedForce));
#endif
#if UNITY_ANDROID
rb.AddForce(GetGyroForces);
#endif
}
I am trying to create a game in Unity where the player can only move in the direction it is facing, but the following code allows the player to move in all 4 directions.
(This is for a 3D project)
Any help would be appreciated! Thanks!
public class PlayerController : MonoBehaviour {
public float speed;
private Rigidbody rb;
void Start() {
rb = GetComponent<Rigidbody>();
}
void FixedUpdate() {
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
rb.AddForce(movement * speed);
}
}
So I didn't get what you wanted: first you said you wanted it to move only forward, then the only thing you have to do is get when he pressed a key and move forward while is not unpressed.
If you wanted to say that it can move all directions BUT only one at a time, the you will have to put the same code but with some changes:
First of all to make it move forward you have to get the forward of the transform, otherwise it will move in the same direction if you rotate it (you don't want that, no?).
Vector3 moveDirection = (transform.forward * Input.GetAxis("Vertical") + transform.right * Input.GetAxis("Horizontal")).normalized;
moveDirection.y = 0;
rb.velocity = moveDirection;
Then, to make that it ONLY moves to one direction at a time, you have to put the priority of the greatest axis number and if it's equal then you should think if you want to move forward or right (with it's axis value).
From the code you posted, I'm not sure where you are storing the player's facing-direction. However, I presume that it is stored as a Quaternion. If you have a player rotation quaternion called playerRotation, then you could do this (warning - untested):
Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
Vector3 normal = playerRotation * Vector3.forward;
Vector3 movement = Vector3.Dot(normal, input) * input;
If the game is first-person, then you can take a shortcut and just use Camera.current.transform.forward instead of the normal vector.
This will project the input direction onto the normal with the player's facing direction so that your movement force can only be in that direction.
hey guys i've something here to ask about how does really the velocity on unity works ??? i've been working on a project recently, i want to create the bouncing ball games, so whenever the ball hit the collider, it will be bounced depends on the position that have been hit.
i'm using the getComponent().velocity, but somehow the ball doesn't bounce really well, and whenever the ball hit the middle of collider, it should be bounced back without changing the direction .. please help !!! any help would be grateful ... here's my code :
float getBallPos(Vector2 ballPos, Vector2 boxPos, float boxWide ){
return (ballPos.x - boxPos.x)/boxWide ;
} ---> to get the bounce direction
void OnCollisionEnter2D (Collision2D other){
isHit = true;
if (other.gameObject.tag == "up") {
float x = getBallPos (transform.position, other.transform.position, other.collider.bounds.size.x);
Vector2 dir = new Vector2 (x, 1).normalized;
Debug.Log ("normalized : " + dir);
GetComponent<Rigidbody2D> ().velocity = dir * 5f;
}else if (other.gameObject.tag == "down") {
float x = getBallPos (transform.position, other.transform.position, other.collider.bounds.size.x);
Vector2 dir = new Vector2 (x, -1).normalized;
Debug.Log ("normalized : " + dir);
GetComponent<Rigidbody2D> ().velocity = dir * 5f;
}
}
You should create a Physics Material 2D with a high bounciness and low friction and apply it to your collider2D (you should see the values until you feel comfortable with it.
You create them in Assets->Create->Physics2D Material.
What you are trying yo do is simulate physics and it requires a somewhat complex mathematical model.
I have the following code which works really well for scrolling map using the draggable mouse. I am trying to define limits so that I cannot scroll too far in either the x or y co-ordinates. I've seen various examples of code, such as:
"transform.position.x = Mathf.Clamp(-100, 100);" though have not been able to incorporate it into the code. I am a bit of a beginner to all this and have just done a 2D tutorial animating zombies and have a camera that can scroll, but would like to add limits to how far it can scroll in any given directions.
Thanks heaps
Adam
using UnityEngine;
using System.Collections;
public class ViewDrag : MonoBehaviour {
Vector3 hit_position = Vector3.zero;
Vector3 current_position = Vector3.zero;
Vector3 camera_position = Vector3.zero;
float z = 0.0f;
// Use this for initialization
void Start () {
}
void Update(){
if(Input.GetMouseButtonDown(0)){
hit_position = Input.mousePosition;
camera_position = transform.position;
}
if(Input.GetMouseButton(0)){
current_position = Input.mousePosition;
LeftMouseDrag();
}
}
void LeftMouseDrag(){
// From the Unity3D docs: "The z position is in world units from the camera." In my case I'm using the y-axis as height
// with my camera facing back down the y-axis. You can ignore this when the camera is orthograhic.
current_position.z = hit_position.z = camera_position.y;
// Get direction of movement. (Note: Don't normalize, the magnitude of change is going to be Vector3.Distance(current_position-hit_position)
// anyways.
Vector3 direction = Camera.main.ScreenToWorldPoint(current_position) - Camera.main.ScreenToWorldPoint(hit_position);
// Invert direction to that terrain appears to move with the mouse.
direction = direction * -1;
Vector3 position = camera_position + direction;
transform.position = position;
}
}
What exactly is the error you are getting? I imagine it is something along the lines of being unable to modify the return value of position because it is not a variable.
If this is the case, you should however be able to set the whole position vector at once. So try something along the lines of this:
var pos = transform.position;
transform.position = new Vector3(
Math.clampf(pos.x, -100, 100),
Math.clampf(pos.y, -100, 100),
pos.z
);
You may need to swap around clamping Y and Z, depending on how you are using them.