Basically I want to make bouncing stick and rotate control, with the left-right button.i'm facing an issue that the rotate not good as I expected because it won't follow my button like being affected by something after bouncing,
I'm using 2d physics material with friction = 1 and Bounciness = 0.9797 for perfect bouncing also attached to rigidbody2d.
I don't know, should I attach it on collider?
here my Player control Script:
public Rigidbody2D r2d;
public float vertical;
public float horizontal;
public Joystick joystick;
private void Start() {
r2d = gameObject.GetComponent < Rigidbody2D > ();
joystick = FindObjectOfType < Joystick > ();
}
private void Update() {
Movement();
}
public void Movement() {
r2d.velocity = r2d.velocity.normalized * 7f;
//horizontal = joystick.Horizontal;
//vertical = joystick.Vertical;
//if (horizontal == 0 && vertical == 0)
//{
// Vector3 curRot = transform.localEulerAngles;
// Vector3 homeRot = transform.localEulerAngles;
// transform.localEulerAngles = Vector3.Slerp(curRot, homeRot, Time.deltaTime * 2);
//}
//else
//{
// transform.localEulerAngles = new Vector3(0f, 0f, Mathf.Atan2(horizontal, vertical) * -180 / Mathf.PI);
//}
}
public Vector3 target;
public float rotationSpeed = 10f;
public float offset = 5;
public void turnLeft() {
Vector3 dir = target - transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
Quaternion rotation = Quaternion.Euler(new Vector3(0, 0, angle + offset));
transform.rotation = Quaternion.Slerp(transform.rotation, -rotation, rotationSpeed * Time.deltaTime);
}
public void turnRight() {
Vector3 dir = target - transform.position;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
Quaternion rotation = Quaternion.Euler(new Vector3(0, 0, angle + offset));
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, rotationSpeed * Time.deltaTime);
}
Whenever there is a Rigidbody/Rigidbody2D involved you do not want to manipulate anything via the .transform component!
This breaks the physics, collision detection and leads to strange movements basically the transform "fighting" against physics for priority.
What you rather want to do would be e.g. adjusting the Rigidbody2D.angularVelocity
public void turnLeft()
{
// Note that Time.deltaTime only makes sense if this is actually called every frame!
r2d.angularVelocity -= rotationSpeed * Time.deltaTime;
}
public void turnRight()
{
r2d.angularVelocity += rotationSpeed * Time.deltaTime;
}
I am making a 3D game but my player can only move on the X and Y axis. I have a player with an attached camera following my mouse, but I only want it to follow up to a max radius distance from Vector3.zero, even if my mouse is beyond those bounds.
I have tried repositioning the player to the max distance on radius every frame it tries to follow the mouse outside its bounds, but this causes camera jitters even in LateUpdate.
void LateUpdate()
{
if (Input.GetMouseButtonDown(0)) {
firstTouchPos = movementCam.ScreenPointToRay(Input.mousePosition);
playerPos = transform.position;
}
if (Input.GetMouseButton(0)) {
Ray currentTouchPos = movementCam.ScreenPointToRay(Input.mousePosition);
Vector2 direction = currentTouchPos.origin - firstTouchPos.origin;
float distance = Vector3.Distance(transform.position, Vector3.zero);
if (distance >= radius) {
targetPosition = direction.normalized * radius;
} else {
targetPosition = playerPos + direction * touchSensitivity;
}
}
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * followSpeed);
}
I'm thinking there must be a way to clamp the positioning of the player to a radius so that I don't have to "leash" him back by repositioning him through code every frame.
You should try using Vector3.ClampMagnitude().
The solution was to use Clamp Magnitude.
void LateUpdate()
{
if (Input.GetMouseButtonDown(0)) {
firstTouchPos = movementCam.ScreenPointToRay(Input.mousePosition);
playerPos = transform.position;
}
if (Input.GetMouseButton(0)) {
// targetPosition will follow finger movements
Ray currentTouchPos = movementCam.ScreenPointToRay(Input.mousePosition);
Vector2 direction = currentTouchPos.origin - firstTouchPos.origin;
targetPosition = playerPos + direction * touchSensitivity;
}
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * followSpeed);
transform.position = Vector3.ClampMagnitude(transform.position, radius);
}
I'm trying to make a simple game where a player flies a cube through a series of gates. I'm running into a problem where the prefab of the player cube appears as in the scene when instantiated GameObject.Instantiate(Resources.Load("CubePrefab")), before it is cloned. This is unexpected, because I'm doing the exact same loading scheme for a different prefab, and it doesn't create this duplication where the prefab exists alongside its clones. Am I misunderstanding how prefabs work, or did I mess up a single line somewhere?
Below is a screenshot- gates in red, player cubes in blue. Selected in the hierarchy are the player cube prefab and gate prefab. Note that the player prefab appears as an actual cube.
I've attached code below for the GameMap/Gates, which create gate clones from a prefab properly, and the Player/Cube, which do not.
GameMap.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameMap {
private GameObject gatePrefab = GameObject.Instantiate(Resources.Load("GatePrefab")) as GameObject;
public GameMap() {}
public void Setup () {
Vector3 position;
Quaternion rotation;
position = new Vector3(0, 0, 0);
rotation = Quaternion.identity;
CreateGate(position, rotation, 10.0f, 2.0f, "Gate 1");
position = new Vector3(0, 0, 20);
rotation = Quaternion.identity * Quaternion.Euler(0, 45, 0);
CreateGate(position, rotation, 10.0f, 1.0f, "Gate 2");
position = new Vector3(20, 0, 20);
rotation = Quaternion.identity * Quaternion.Euler(0, 90, 0);
CreateGate(position, rotation, 8.0f, 1.0f, "Gate 3");
CreateGround();
}
private void CreateGate(Vector3 position, Quaternion rotation, float lengthOfSide, float thickness, string name) {
// Create the gates, and call the "Initialize" method to populate properties as Unity doesn't have constructors.
GameObject clone = GameObject.Instantiate(gatePrefab, position, rotation) as GameObject;
clone.name = name;
clone.GetComponent<Gate>().Initialize(lengthOfSide, thickness);
}
private void CreateGround() {
GameObject ground = GameObject.CreatePrimitive(PrimitiveType.Plane);
ground.name = "Ground";
ground.transform.localPosition = new Vector3(0, -10, 0);
ground.transform.localRotation = Quaternion.identity;
ground.transform.localScale = new Vector3(50, 1, 50);
ground.GetComponent<Renderer>().material.color = Color.grey;
}
}
Gate.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gate : MonoBehaviour {
float lengthOfSide;
float thickness;
public void Initialize (float lengthOfSide, float thickness) {
this.lengthOfSide = lengthOfSide;
this.thickness = thickness;
}
// Use this for initialization
void Start () {
SetupRigidBody();
Setup3dEntities();
}
void SetupRigidBody() {
Rigidbody rb = this.gameObject.AddComponent<Rigidbody>();
rb.detectCollisions = true;
rb.mass = 1000;
rb.useGravity = false;
}
// Create the physical gate
void Setup3dEntities() {
Vector3 position;
Vector3 scale;
float lengthOfVeritcalSegment = lengthOfSide - (2 * thickness);
float yPosHorizontalSegment = (lengthOfSide - thickness) / 2;
float xPosVerticalSegment = lengthOfSide - thickness;
// Bottom
position = new Vector3(0, -yPosHorizontalSegment, 0);
scale = new Vector3(lengthOfSide, thickness, thickness);
CreatePrimitiveCube(position, scale);
// Top
position = new Vector3(0, yPosHorizontalSegment, 0);
scale = new Vector3(lengthOfSide, thickness, thickness);
CreatePrimitiveCube(position, scale);
// Left
position = new Vector3(xPosVerticalSegment/2, 0, 0);
scale = new Vector3(thickness, lengthOfVeritcalSegment, thickness);
CreatePrimitiveCube(position, scale);
// Right
position = new Vector3(-xPosVerticalSegment/2, 0, 0);
scale = new Vector3(thickness, lengthOfVeritcalSegment, thickness);
CreatePrimitiveCube(position, scale);
}
void CreatePrimitiveCube(Vector3 position, Vector3 scale) {
// Create a primitive cube. Note that we want to set the position and rotation to match the parent!
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.transform.parent = gameObject.transform; // TODO: is this safe to have here?
cube.transform.localPosition = position;
cube.transform.localRotation = Quaternion.identity;
cube.transform.localScale = scale;
// TODO: Make a better color/material mechanism!
cube.GetComponent<Renderer>().material.color = Color.red;
// Debug.Log("Cube.parent: " + cube.transform.parent.gameObject.name);
// Debug.Log("Cube.localScale: " + cube.transform.localScale);
}
}
Player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player
{
private GameObject cubePrefab = GameObject.Instantiate(Resources.Load("CubePrefab")) as GameObject;
public float moveSpeed = 3f;
private GameObject playerObject;
private Vector3 startingPosition;
private Quaternion startingRotation;
private Transform transform;
public Player(){}
public void Setup() {
startingPosition = new Vector3(0, 0, 0);
startingRotation = Quaternion.identity;
Vector3 scale = new Vector3(2, 2, 2);
GameObject clone = GameObject.Instantiate(cubePrefab, startingPosition, startingRotation) as GameObject;
clone.name = "Playercube";
clone.GetComponent<Cube>().Initialize();
playerObject = clone;
// Make main camera child of drone
Camera.main.transform.parent = playerObject.transform;
}
public void Move(float verticalInput, float horizontalInput) {
float moveSpeed = 3f;
float verticalSpeed = verticalInput * moveSpeed;
float horizontalSpeed = horizontalInput * moveSpeed;
Debug.Log("Player.Move verticalSpeed:"+verticalSpeed+" horizontalSpeed:"+horizontalSpeed);
//Moves Forward and back along z axis //Up/Down
playerObject.transform.Translate(Vector3.forward * Time.deltaTime * verticalSpeed);
//Moves Left and right along x Axis //Left/Right
playerObject.transform.Translate(Vector3.right * Time.deltaTime * horizontalSpeed);
}
}
Cube.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Cube : MonoBehaviour {
public void Initialize () {
}
// Use this for initialization
void Start () {
Vector3 position = new Vector3(0, 0, 0);
Vector3 scale = new Vector3(2, 2, 2);
CreatePrimitiveCube(position, scale);
// SetupPhysics();
}
void CreatePrimitiveCube(Vector3 position, Vector3 scale) {
// Create a primitive cube. Note that we want to set the position and rotation to match the parent!
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.transform.parent = gameObject.transform;
cube.transform.localPosition = position;
cube.transform.localRotation = Quaternion.identity;
cube.transform.localScale = scale;
// TODO: Make a better color/material mechanism!
cube.GetComponent<Renderer>().material.color = Color.blue;
}
void SetupPhysics() {
Rigidbody rb = gameObject.AddComponent<Rigidbody>();
rb.detectCollisions = true;
rb.mass = 1;
rb.useGravity = false;
gameObject.AddComponent<MeshRenderer>();
BoxCollider boxCollider = gameObject.AddComponent<BoxCollider>();
MeshRenderer renderer = gameObject.GetComponent<MeshRenderer>();
boxCollider.center = renderer.bounds.center;
boxCollider.size = renderer.bounds.size;
}
}
I think the problem is:
private GameObject cubePrefab = GameObject.Instantiate(Resources.Load("CubePrefab")) as GameObject;
You Instantiate the prefab directly after loading it, i don't think that this is what you want, because this will create the additional object in your scene.
I think you want just load the prefab and instantiate it later in this case it should work if you change the line to:
private GameObject cubePrefab = Resources.Load("CubePrefab") as GameObject;
Now you will only load the prefab from the resources and you can instantiate it later
I'm trying to spin a bottle (I'm calculating the first pos and end pos of the mouse) and apply forces to it according to the 'swipe' length/time. After the initial swipe, the bottle should keep rotating based on the force of the swipe, and then stop after few seconds.
I hope you could help me here. Thanks!
bottle interface
This is what I tried to do, but it doesn't work well:
public Rigidbody bottle;
bool isSwiping;
Touch thisTouch;
Vector2 origPos;
Vector2 endPos;
float touchSpeed;
Vector3 Torque;
float timeStart; float timeEnd;
void OnMouseDown()
{
timeStart = Time.time;
origPos = Input.mousePosition;
}
void OnMouseDrag()
{
isSwiping = true;
}
void OnMouseUp()
{
if (isSwiping)
{
timeEnd = Time.time;
endPos = Input.mousePosition;
Vector2 deltaPosition = endPos - origPos;
touchSpeed = deltaPosition.magnitude / (timeEnd-timeStart);
Torque = new Vector3(touchSpeed * 500f, 0, 0);
}
}
void Update()
{
}
void FixedUpdate()
{
if (isSwiping) bottle.AddRelativeTorque(Torque);
}
Try use this code:
public Rigidbody bottle;
bool isSwiping;
Touch thisTouch;
Vector2 origPos;
Vector2 endPos;
float touchSpeed;
Vector3 Torque;
float timeStart; float timeEnd;
void OnMouseDown()
{
timeStart = Time.time;
origPos = Input.mousePosition;
}
void OnMouseUp()
{
timeEnd = Time.time;
endPos = Input.mousePosition;
Vector2 deltaPosition = endPos - origPos;
touchSpeed = deltaPosition.magnitude / (timeEnd-timeStart);
Torque = new Vector3(touchSpeed * 500f, 0, 0);
isSwiping = true;
}
void FixedUpdate()
{
if (isSwiping) bottle.AddRelativeTorque(Torque);
}
I'm directly modifying an object position by moving it around with the mouse button.
Vector3 touchPosition = Camera.main.ScreenToWorldPoint (Input.mousePosition);
Vector3 touchPosition = new Vector3 (touchPosition.x, touchPosition.y, transform.position.z);
touchPosition.z = transform.position.z;
if(Input.GetMouseButton(0)) {
transform.position = newPosition;
}
What I want to find out is what is the average velocity of the object in the last few frames. Any idea how to do this?
Probably would look something like this:
Vector3 velocity;
Vector3 lastPosition = transform.position;
Vector3 touchPosition = Camera.main.ScreenToWorldPoint (Input.mousePosition);
Vector3 touchPosition = new Vector3 (touchPosition.x, touchPosition.y, transform.position.z);
touchPosition.z = transform.position.z;
if(Input.GetMouseButton(0)) {
transform.position = newPosition;
velocity = (newPosition - lastPosition) / Time.deltaTime;
}