I have a camera that I control it with the (W,A,S,D) keys...
What I want to do is that when press left mouse click ("Fire1") the camera turns back to the first position animatedly.
Is it possible to do it with Mecanim and create a dynamic animation file to do it?!
That's my code:
void Update ()
{
if (Input.GetKey(KeyCode.W))
{
Cam.transform.Rotate (0, 0, 2);
}
if (Input.GetKey(KeyCode.S) )
{
Cam.transform.Rotate (0, 0, -2);
}
if (Input.GetKey(KeyCode.D))
{
Cam.transform.Rotate (0, 2, 0);
}
if (Input.GetKey(KeyCode.A))
{
Cam.transform.Rotate (0, -2, 0);
}
My camera position and rotation at the start is (0,0,0) but when I control my camera these parameters change so I want my camera to turns back to the first position (0,0,0) animatedly when I press left mouse button...
Something like:
if (Input.GetButtonDown("Fire1"))
{
Cam.GetComponent<Animation> ().Play ();
}
Instead of the animation, you could smooth out the camera movement:
Add the following variables to your script, the first one is used to control the amount of smoothness you want:
public float smoothTime = 0.2f;
private Vector3 velocity = Vector3.zero;
And then:
if (Input.GetButtonDown("Fire1")) {
Vector3 targetPosition = new Vector3(0,0,0);
Cam.transform.position = Vector3.SmoothDamp(Cam.transform.position, targetPosition, ref velocity, smoothTime);
}
From your code, I can see that you are only changing rotation of the Camera. Following is my solution to it.
It saves the starting rotation at the start and later lerps to the start rotation when "Fire1" is pressed.
However, position is not handled here, as there's no position change in your code. But the concept is same. You can change the position in a similar way.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CamTest : MonoBehaviour {
public float animSpeed = 1.0f;
public Camera Cam;
private Quaternion startRotation;
private bool doRotate = false;
// Use this for initialization
void Start () {
//Cam = GetComponent<Camera> ();
startRotation = transform.rotation;
}
void Update () {
if (Input.GetKey(KeyCode.W))
{
Cam.transform.Rotate (0, 0, 2);
}
if (Input.GetKey(KeyCode.S) )
{
Cam.transform.Rotate (0, 0, -2);
}
if (Input.GetKey(KeyCode.D))
{
Cam.transform.Rotate (0, 2, 0);
}
if (Input.GetKey(KeyCode.A))
{
Cam.transform.Rotate (0, -2, 0);
}
if (Input.GetButtonDown("Fire1")) {
Debug.Log ("Fire1");
doRotate = true;
}
if(doRotate) DoRotation ();
}
void DoRotation(){
if (Quaternion.Angle(Cam.transform.rotation, startRotation) > 1f) {
Cam.transform.rotation = Quaternion.Lerp(Cam.transform.rotation, startRotation,animSpeed*Time.deltaTime);
} else {
Cam.transform.rotation = startRotation;
doRotate = false;
}
}
}
Related
I have such a problem, maybe someone will help. I am making a game and I need to make a dice that goes in the direction opposite to the click. For example, clicking on the back of a cube moves it forward, etc. Gravity must act on the cube as shown in the figure below. Unfortunately, the cube does not change height, but only the position of X and Z. Please help.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveCube : MonoBehaviour
{
Vector3 movePosition;
public float time = 0.02f;
[HideInInspector]
public bool blockClick = false;
private void Start()
{
movePosition = transform.position;
}
private void Update()
{
blockClick = false;
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit raycastHit;
if (Physics.Raycast(ray, out raycastHit))
{
string hitName = raycastHit.transform.name;
if (hitName == "MoveCube")
{
move(raycastHit);
blockClick = true;
}
}
}
transform.position = Vector3.Lerp(
transform.position,
movePosition,
time);
}
public void move(RaycastHit raycastHit)
{
Vector3 incomingVec = raycastHit.normal - Vector3.up;
// South
if (incomingVec == new Vector3(0, -1, -1))
{
movePosition = movePosition + new Vector3(0, 0, 1);
return;
}
// North
if (incomingVec == new Vector3(0, -1, 1))
{
movePosition = movePosition + new Vector3(0, 0, -1);
return;
}
// West
if (incomingVec == new Vector3(-1, -1, 0))
{
movePosition = movePosition + new Vector3(1, 0, 0);
return;
}
// East
if (incomingVec == new Vector3(1, -1, 0))
{
movePosition = movePosition + new Vector3(-1, 0, 0);
return;
}
}
}
From what I know, changing the transform.position of a gameObject with a rigidbody will mess with Unity's physics, and it won't work as intended. I suggest trying to apply a force from the position of the mouse's click instead of moving the cube's position manually (if this makes sense to do for your purposes). Here is the documentation for Rigidbody.AddForce
I'm pretty new to Unity, and recently I've begun working on my first mobile game using C#, and suddenly I get the CS0117 error and I don't know why since my code is pretty simple and the console won't specify in which line the error occurs. I received the error when I wrote the simple line:
transform.position = new Vector3 (0, 0, 0);
in my player script to set it's position to the same as the position of the camera. I don't think that this has anything to do with the script itself, but that it is a problem with my phone, but I don't know what the problem is.
In case you need it, here are the full scripts of the player and the camera.
player script:
public class playerScript : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
transform.position = new Vector3 (0, 0, 0);
}
// Update is called once per frame
void Update()
{
//movement
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
Vector3 touchPosition = Camera.main.ScreenToWorldPoint(touch.position);
touchPosition.z = 0f;
transform.position = touchPosition;
}
//borders
if (transform.position.x >= 2.3f)
{
transform.position = new Vector3(2.3f ,transform.position.y, 0);
}
if (transform.position.x <= -2.3f)
{
transform.position = new Vector3(-2.3f ,transform.position.y, 0);
}
if (transform.position.y >= 4.5f)
{
transform.position = new Vector3(transform.position.x, 4.5f, 0);
}
if (transform.position.y <= -4.5f)
{
transform.position = new Vector3(transform.position.x, -4.5f, 0);
}
}
}
Camera script:
public class cameraScript : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
transform.position = new Vector3 (0, 0, 0);
}
// Update is called once per frame
void Update()
{
}
}
I'm currently trying to use a Physics2D.BoxCast() to manually detect collisions in a test project. I got everything set up with the help of a tutorial I watched a while ago but for some reason the box cast seems to be above the Box Collider that I attached its size to. I'm not the best a writing issues out so Ill have a gif bellow that better shows what the problem is, as well as I'll attach the code I used to detect the collisions.
This is when I try to collide from +y on the axis
This is when I try to collide from -y on the axis:
I've tried looking up more on how Physics2D.BoxCast work and why it would seem to be pushed down but I havent found anything helpful just yet.
Here's the code I use for movement and manual collision detection.
using UnityEngine;
public class Player : MonoBehaviour {
public float speed = 2f;
private BoxCollider2D boxCollider;
private SpriteRenderer sprite;
private Vector3 moveDelta;
private RaycastHit2D hit2D;
protected virtual void Awake() {
boxCollider = GetComponent<BoxCollider2D>();
sprite = GetComponent<SpriteRenderer>();
}
protected virtual void Update() {
float x = Input.GetAxisRaw("Horizontal");
float y = Input.GetAxisRaw("Vertical");
moveDelta = new Vector3(x, y, 0);
// Flips the sprite based on the direction its moving on the X
if (moveDelta.x > 0)
{
sprite.flipX = false;
}
if (moveDelta.x < 0)
{
sprite.flipX = true;
}
// Manual detection for collisions
hit2D = Physics2D.BoxCast(transform.position, boxCollider.size, 0, new Vector2(moveDelta.x, 0), Mathf.Abs(moveDelta.x * Time.deltaTime), LayerMask.GetMask("Blocking", "Actor"));
if (hit2D.collider == null)
{
transform.Translate(moveDelta.x * Time.deltaTime, 0, 0);
}
hit2D = Physics2D.BoxCast(transform.position, boxCollider.size, 0, new Vector2(0, moveDelta.y), Mathf.Abs(moveDelta.y * Time.deltaTime), LayerMask.GetMask("Blocking", "Actor"));
if (hit2D.collider == null)
{
transform.Translate(0, moveDelta.y * Time.deltaTime, 0);
}
}
}
The transform.position used in the box cast was not at the center of the collider. Thus casting the BoxCast above where the collider was. The solution was to place an empty game object in the center of the collider. Again I'm sorry about the way I explain things I hope the pictures bellow can help you understand better..
Code wise it was a simple fix that took me too long to figure out..
using UnityEngine;
public class Player : MonoBehaviour {
public float speed = 2f;
public GameObject boxcastCenter;
private BoxCollider2D boxCollider;
private SpriteRenderer sprite;
private Vector3 moveDelta;
private RaycastHit2D hit2D;
protected virtual void Awake() {
boxCollider = GetComponent<BoxCollider2D>();
sprite = GetComponent<SpriteRenderer>();
}
protected virtual void Update() {
float x = Input.GetAxisRaw("Horizontal");
float y = Input.GetAxisRaw("Vertical");
moveDelta = new Vector3(x, y, 0);
// Flips the sprite based on the direction its moving on the X
if (moveDelta.x > 0)
{
sprite.flipX = false;
}
if (moveDelta.x < 0)
{
sprite.flipX = true;
}
// Manual detection for collisions changes were made in the transform.position bellow
hit2D = Physics2D.BoxCast(boxcastCenter.transform.position, boxCollider.size, 0, new Vector2(moveDelta.x, 0), Mathf.Abs(moveDelta.x * Time.deltaTime), LayerMask.GetMask("Blocking", "Actor"));
if (hit2D.collider == null)
{
transform.Translate(moveDelta.x * Time.deltaTime, 0, 0);
}
hit2D = Physics2D.BoxCast(boxcastCenter.transform.position, boxCollider.size, 0, new Vector2(0, moveDelta.y), Mathf.Abs(moveDelta.y * Time.deltaTime), LayerMask.GetMask("Blocking", "Actor"));
if (hit2D.collider == null)
{
transform.Translate(0, moveDelta.y * Time.deltaTime, 0);
}
}
}
I have a grid consisting of 16 tiles. Now basically I want the user to find a path to the final location by moving randomly on the choices he has within the grid.
As of now I managed to create the functions for moving a step up, down, left and right. The issue arises when I'm trying to code in random movement. Ideally this is setup in a way that he can't go off bounds from the grid.
This is what I got going:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour
{
void Up()
{
//get the Input from Horizontal axis
float horizontalInput = Input.GetAxis("Horizontal");
//get the Input from Vertical axis
float verticalInput = Input.GetAxis("Vertical");
//update the position
transform.position = transform.position + new Vector3(0, 1.5f, 0);
//output to log the position change
Debug.Log(transform.position);
}
void Down()
{
//get the Input from Horizontal axis
float horizontalInput = Input.GetAxis("Horizontal");
//get the Input from Vertical axis
float verticalInput = Input.GetAxis("Vertical");
//update the position
transform.position = transform.position + new Vector3(0, -1.5f, 0);
//output to log the position change
Debug.Log(transform.position);
}
void Left()
{
//get the Input from Horizontal axis
float horizontalInput = Input.GetAxis("Horizontal");
//get the Input from Vertical axis
float verticalInput = Input.GetAxis("Vertical");
//update the position
transform.position = transform.position + new Vector3(-1.5f, 0, 0);
//output to log the position change
Debug.Log(transform.position);
}
void Right()
{
//get the Input from Horizontal axis
float horizontalInput = Input.GetAxis("Horizontal");
//get the Input from Vertical axis
float verticalInput = Input.GetAxis("Vertical");
//update the position
transform.position = transform.position + new Vector3(1.5f, 0, 0);
//output to log the position change
Debug.Log(transform.position);
}
void Start()
{
var finalLocation = new Vector3(-0.5f, 0.5f, 0);
var currentLocation = transform.position;
while (currentLocation != finalLocation)
{
int randomNum = Random.Range(0, 3);
if (randomNum == 0)
{
Up();
}
else if (randomNum == 1)
{
Down();
}
else if (randomNum == 2)
{
Left();
}
else if (randomNum == 3)
{
Right();
}
}
}
}
UPDATED WORKING CODE:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Move : MonoBehaviour
{
void Up()
{
//update the position
transform.position = transform.position + new Vector3(0, 1.5f, 0);
//output to log the position change
Debug.Log(transform.position);
}
void Down()
{
//update the position
transform.position = transform.position + new Vector3(0, -1.5f, 0);
//output to log the position change
Debug.Log(transform.position);
}
void Left()
{
//update the position
transform.position = transform.position + new Vector3(-1.5f, 0, 0);
//output to log the position change
Debug.Log(transform.position);
}
void Right()
{
//update the position
transform.position = transform.position + new Vector3(1.5f, 0, 0);
//output to log the position change
Debug.Log(transform.position);
}
void Update()
{
var finalLocation = new Vector3(2.5f, 2.0f, -2.0f);
var currentLocation = transform.position;
int randomNum = Random.Range(0, 4);
if (currentLocation != finalLocation) {
if (randomNum == 0)
{
Up();
}
else if (randomNum == 1)
{
Down();
}
else if (randomNum == 2)
{
Left();
}
else if (randomNum == 3)
{
Right();
}
return;
}
}
}
My last issue is how I can limit this randomness to only stick to the grid and not go off grid. Any thoughts?
Here are some problems:
horizontalInput and verticalInput are never used inside your functions
while(currentLocation != finalLocation) This condition can fail in some situations. Unity uses float for the coordinates, meaning it needs to be exactly on the same position, every decimal place need to be the same.
Random.Range(0, 3) will return a random number between 0 (inclusive) and 3 (exclusive), so the only possible values will be 0, 1 and 2. The script will never call the Right() function.
Unity uses one thread to run your scripts by default, if you put a while loop to move the object to a location it will freeze the entire game till the object is at the proper place. I recommend you to use the Update() function, it gets called every frame.
Several problems:
Your object is stuck in an endless while loop because it isn't allowed to exit (and do things like render the frame, take input from the user, etc) until your random movement script reaches its finalLocation. You aren't giving the game time to do anything else.
You almost certainly want this to be a coroutine or an Update function.
Random.Range returns an int in the range min (inclusive) to max (exclusive), so your call to it will never return 3.
I need to move a cube by clicking and dragging in C# Unity3D. My code currently creates the cubes by cilcking a button.
using UnityEngine;
using System.Collections;
public class CDraggable : MonoBehaviour
{
Texture btnimg;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
Update ()
{
//here to write mousedrag code.
}
void OnGUI()
{
if (GUI.Button(new Rect(400, 250, 50, 50), btnimg))
{
//Debug.Log("Clicked the button with an image");
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.transform.position = new Vector3(-0.7F, 2, 0);
}
}
}
Add the script DragRigidbody.js to your camera. It is included in unity's default assets at StandardAssets/Scripts/GeneralScripts/, and it does exactly what you want.
This might help you.. :)
Vector2 screenPoint = Vector2.Zero ;
void OnMouseDown()
{
screenPoint = Camera.main.WorldToScreenPoint(scanPos);
offset = scanPos - Camera.main.ScreenToWorldPoint(
new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z));
}
Vector3 curScreenPoint = Vector3.Zero;
Vector3 curPosition = Vector3.Zero;
void OnMouseDrag()
{
curScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z);
curPosition = Camera.main.ScreenToWorldPoint(curScreenPoint) + offset;
transform.position = curPosition;
}
Maybe this will help if your game is 2D, I think.
void Update{
if (Input.GetMouseButton())
{
transform.position = Input.mousePosition;
}
}