Hi everybody I am having a problem with my game, the problem is based when I switch the materials so it can face the other direction (it is a 2d game). This affects the animation which is controlled by the renderer.material.mainTextureOffset but I have no idea why this is not working.
code in c#:
using UnityEngine;
using System.Collections;
public class character : MonoBehaviour {
public float forwardSpeed = 10.0f;
public Material newMaterialRefcs1;
public Material newMaterialRefcs2;
// Use this for initialization
void Start () {
}
//error is occurring here !!!!!!!! below Important. The 2 if statements below
// Update is called once per frame
void Update () {
if( Input.GetKey(KeyCode.D)){
renderer.material.mainTextureOffset = new Vector2(0.25f, 0);
transform.position += -transform.right * forwardSpeed * Time.deltaTime;
renderer.material = newMaterialRefcs1;
}if( Input.GetKey(KeyCode.A)){
renderer.material.mainTextureOffset = new Vector2(0.25f, 0);
transform.position += transform.right * forwardSpeed * Time.deltaTime;
renderer.material = newMaterialRefcs2;
}
}}
I'm not sure exactly what your problem is but it sounds like you're trying to adjust one setting in the first script then add a new material in the second script. If that is the case then, when you assign the new material in the second script you are replacing the material completely meaning the renderer.material.mainTextureOffset.x that you set in the first gets overwritten.
Try keeping the offset in a separate variable that you can assign to the new texture when it is added in the second script.
Try to use other shader. Diffuse, for example.
Also, check in inspector, is this value really changed. May You rewrite it in other script?
I have figured it out with some help from the unity forums took a while but here it is:
using UnityEngine;
using System.Collections;
public class character : MonoBehaviour {
public float forwardSpeed = 20.0f; public float rot = 0f;public float jumpSpeed = 100;public float gravity = 30f;
public Material newMaterialRefcs1;
public Material newMaterialRefcs2;
void Start () {
}
public float scrollSpeed = 0.25F;
void Update () {
if( Input.GetKey(KeyCode.RightArrow)){
scrollSpeed += 0.25f;
transform.position += -transform.right * forwardSpeed * Time.deltaTime;
renderer.material = newMaterialRefcs1;
float offset = scrollSpeed;
renderer.material.SetTextureOffset("_MainTex", new Vector2(offset, 0));
}if( Input.GetKey(KeyCode.LeftArrow)){
scrollSpeed += 0.25f;
transform.position += transform.right * forwardSpeed * Time.deltaTime;
renderer.material = newMaterialRefcs2;
float offset = scrollSpeed;
renderer.material.SetTextureOffset("_MainTex", new Vector2(offset, 0));
}
Vector3 isgrounded = transform.TransformDirection(Vector3.up);
if( Input.GetKeyDown(KeyCode.Space)&& Physics.Raycast(transform.position, isgrounded, 6)){
transform.position -= transform.up * jumpSpeed * Time.deltaTime*2;
}
Physics.gravity = new Vector3(0, gravity, 0);
transform.rotation = Quaternion.Euler(0, 0, transform.rotation.eulerAngles.z);
}
}
Related
i've following issue. I'm trying to make game with top down view (something like first GTA game). The problem is when i press the key my player is moving, but can't stop. Here you can see my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovemenet : MonoBehaviour
{
private Rigidbody2D m_Rigidbody;
private Transform playerTransform;
public float m_Speed = 100.0f;
// Start is called before the first frame update
void Start()
{
m_Rigidbody = GetComponent<Rigidbody2D>();
playerTransform = GameObject.Find("Player").transform;
}
// Update is called once per frame
void FixedUpdate()
{
Vector3 playerPos = playerTransform.eulerAngles;
if (Input.GetKey(KeyCode.UpArrow))
{
m_Rigidbody.velocity= transform.up * Time.deltaTime * m_Speed;
}
if (Input.GetKey(KeyCode.DownArrow))
{
m_Rigidbody.velocity = transform.up * Time.deltaTime * (-m_Speed);
}
if (Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(0, 0, -1 * m_Speed * Time.deltaTime);
}
if (Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(0, 0, 1 * m_Speed * Time.deltaTime);
}
}
}
'''
Can you please tell me how to fix it? Thanks for your answers.
Note that in general a velocity already is a value in absolute units per second and you don't want to multiply by Time.deltaTime in that case.
Also in general whenever dealing with Physics I wouldn't use transform at all but rather do everything via the Rigidbody.
And then simply when you don't press a key do
if (Input.GetKey(KeyCode.UpArrow))
{
m_Rigidbody.velocity = Quaternion.Euler(0, 0, m_Rigidbody.rotation) * Vector3.up * m_Speed;
}
else if (Input.GetKey(KeyCode.DownArrow))
{
m_Rigidbody.velocity = Quaternion.Euler(0, 0, m_Rigidbody.rotation) * Vector3.down * m_Speed;
}
else
{
m_Rigidbody.velocity = Vector2.zero;
}
For the rotation I would also rather go
m_Rigidbody.rotation += m_Speed * Time.deltaTime;
and
m_Rigidbody.rotation -= m_Speed * Time.deltaTime;
I am making code for a first person physics-based character controller in Unity. The movement is mostly smooth, but when I go up a slope, instead of sliding back down, the character floats in the air slightly while slowly moving downward until it gets back to the ground. This behavior is very strange and unexpected, and I don't really know why this is happening.
The character is an empty object with a capsule and a sphere childed to it. The script is on the empty object, and the rigidbody is on the capsule which is a child to the empty.
Here is the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
float mouseSensitivity;
private float cameraXRotation;
private float cameraYRotation;
private float movementX;
private float movementY;
private Transform playerHeadTransform;
private Transform playerBodyTransform;
private Rigidbody playerRigidBody;
private bool IsJumping;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
playerBodyTransform = transform.GetChild(0).gameObject.GetComponent<Transform>();
playerHeadTransform = transform.GetChild(0).transform.GetChild(0).gameObject.GetComponent<Transform>();
playerRigidBody = transform.GetChild(0).gameObject.GetComponent<Rigidbody>();
playerHeadTransform.transform.rotation = Quaternion.Euler(0f, 0f, 0f);
mouseSensitivity = 750;
IsJumping = false;
}
// Update is called once per frame
void Update()
{
#region CameraStuff
float cameraMouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float cameraMouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
cameraXRotation -= cameraMouseY;
cameraYRotation += cameraMouseX;
cameraXRotation = Mathf.Clamp(cameraXRotation, -90f, 60);
playerHeadTransform.localRotation = Quaternion.Euler(cameraXRotation, 0f, 0f);
playerBodyTransform.localRotation = Quaternion.Euler(0f, cameraYRotation, 0f);
#endregion
//Movement input variables
movementX = Input.GetAxis("Horizontal") * mouseSensitivity * Time.deltaTime;
movementY = Input.GetAxis("Vertical") * mouseSensitivity * Time.deltaTime;
}
void FixedUpdate()
{
playerRigidBody.velocity = playerBodyTransform.TransformDirection(movementX*2, 0, movementY*2);
}
}
Your player not falling down is most probably related to you setting
void FixedUpdate()
{
playerRigidBody.velocity = playerBodyTransform.TransformDirection(movementX*2, 0, movementY*2);
}
if there is gravity involved you rather want to make sure to not overwrite the Y axis and do e.g.
var currentVelocity = playerRigidbody.velocity;
var newVelocity = playerBodyTransform.TransformDirection(movementX * 2, 0, movementY * 2);
// keep the velocity on Y but only if it is currently downwards
// so you can still move up on a slope but fall down with gravity
if(currentVelocity.y < 0) newVelocity.y = currentVelocity.y;
playerRigidBody.velocity = newVelocity;
My code below only works for horizontal movement. Shouldn't the vertical movement be working too? I'm just starting out with basic 2D Unity programming:
public class Player : MonoBehaviour {
//These fields will be exposed to Unity so the dev can set the parameters there
[SerializeField] private float speed = 1f;
[SerializeField] private float upY;
[SerializeField] private float downY;
[SerializeField] private float leftX;
[SerializeField] private float rightX;
private Transform _transformY;
private Transform _transformX;
private Vector2 _currentPosY;
private Vector2 _currentPosX;
// Use this for initialization
void Start () {
_transformY = gameObject.GetComponent<Transform> ();
_currentPosY = _transformY.position;
_transformX = gameObject.GetComponent<Transform> ();
_currentPosX = _transformX.position;
}
// Update is called once per frame
void Update () {
_currentPosY = _transformY.position;
_currentPosX = _transformX.position;
float userInputV = Input.GetAxis ("Vertical");
float userInputH = Input.GetAxis ("Horizontal");
if (userInputV < 0)
_currentPosY -= new Vector2 (0, speed);
if (userInputV > 0)
_currentPosY += new Vector2 (0, speed);
if (userInputH < 0)
_currentPosX -= new Vector2 (speed, 0);
if (userInputH > 0)
_currentPosX += new Vector2 (speed, 0);
CheckBoundary ();
_transformY.position = _currentPosY;
_transformX.position = _currentPosX;
}
private void CheckBoundary(){
if (_currentPosY.y < upY)
_currentPosY.y = upY;
if (_currentPosY.y > downY)
_currentPosY.y = downY;
if (_currentPosX.x < leftX)
_currentPosX.x = leftX;
if (_currentPosX.x > rightX)
_currentPosX.x = rightX;
}
}
If I remove/comment out the _currentPosX and it's related codes then my Vertical movement works. But if I remove/comment out the _currentPosY and it's related codes then my Horizontal movement works.
But how come I'm having trouble getting them to work at the same time? I think I'm just missing something but I can't figure it out since I'm just a beginner at this.
Thanks to whoever can give advise.
EDIT: for further clarification...
I'm coding a simple 2d game that will have the player move in 4-directions using the WASD keys.
W = move up
A = move left
S = move down
D = move right
My main problem is that I can get two of the keys working only in one axis: either A and D is working for Horizontal while W and S are not working at all for Vertical movement or vice-versa.
You don't need those if statements. Just use += to append the input to the current transform position.
Move without Rigidbody:
public float speed = 100;
public Transform obj;
public void Update()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 tempVect = new Vector3(h, v, 0);
tempVect = tempVect.normalized * speed * Time.deltaTime;
obj.transform.position += tempVect;
}
Move Object with Rigidbody2D:
public float speed = 100;
public Rigidbody2D rb;
public void Update()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 tempVect = new Vector3(h, v, 0);
tempVect = tempVect.normalized * speed * Time.deltaTime;
rb.MovePosition(rb.transform.position + tempVect);
}
I suggest using the second code and moving the Rigidbody if you want to be able to detect collison later on.
Note:
You must assign the object to move to the obj slot in the Editor. If using the second code, assign the object with the Rigidbody2D to the rb slot in the Editor.
THIS CODE WORK 100% (you must try it.)
public float moveSpeed = 5;
void Start()
{
}
void Update()
{
if (Input.GetKey(KeyCode.D))
{
transform.position += Vector3.right * moveSpeed * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.A))
{
transform.position += Vector3.right * -moveSpeed * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.W))
{
transform.position += Vector3.up * moveSpeed * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.S))
{
transform.position += Vector3.up * -moveSpeed * Time.deltaTime;
}
}
Try changing the value 0 in the Vector2 functions to current x/ y position...I ran into a similar problem with my project
if (userInputV < 0)
_currentPosY -= new Vector2 (/*current position*/, speed);
I'm having an issue where my gameObject barely jumps at all. I think it has something to do with moveDirection because the jumping works when I comment out p.velocity = moveDirection.
Any suggestions on how to fix this?
using UnityEngine;
using System.Collections;
public class Controller : MonoBehaviour
{
public float jumpHeight = 8f;
public Rigidbody p;
public float speed = 1;
public float runSpeed = 3;
public Vector3 moveDirection = Vector3.zero;
// Use this for initialization
void Start ()
{
p = GetComponent<Rigidbody>();
p.velocity = Vector3.zero;
}
// Update is called once per frame
void Update ()
{
if (Input.GetKeyDown (KeyCode.Space))
{
p.AddForce(new Vector3(0, jumpHeight, 0), ForceMode.Impulse);
}
Move ();
}
void Move ()
{
if(Input.GetKey(KeyCode.D))
{
transform.Rotate(Vector3.up, Mathf.Clamp(180f * Time.deltaTime, 0f, 360f));
}
if(Input.GetKey(KeyCode.A))
{
transform.Rotate(Vector3.up, -Mathf.Clamp(180f * Time.deltaTime, 0f, 360f));
}
moveDirection = new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
if(Input.GetKey(KeyCode.LeftShift))
{
moveDirection *= runSpeed;
}
else
{
moveDirection *= speed;
}
p.velocity = moveDirection;
}
}
Try using a much higher value for your jumpheight variable. I usually go with something in the hundreds.
Because right after doing the AddForce(...) literally within the same frame you override the velocity with moveDirection. You should be adding to the current velocity, instead of overriding it entirely as such:
Vector3 velocity = p.velocity;
p.velocity = velocity + moveDirection;
This is exactly why Unity warns against messing with velocity directly, youd be better off just doing another AddForce(...) for your movement:
p.AddForce(moveDirection * Time.deltaTime);
EDIT:
i don't like digressing too far from the OP's question, but your new problems are probably because you are doing too much with moveDirection half of what i don't even understand why but it should for the most part look like this:
moveDirection = new Vector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical")).normalized;
float _speed = Input.GetKey(KeyCode.LeftShift) ? runspeed : speed;
p.AddForce(moveDirection * _speed * Time.deltaTime);
Okay I figured out how to fix it. Instead of those MoveDirection variables I changed it to
if(Input.GetKey(KeyCode.W)) {
transform.position += transform.forward * Time.deltaTime * speed;
}
if(Input.GetKey(KeyCode.S)) {
transform.position -= transform.forward * Time.deltaTime * speed;
}
and now it works just fine.
I have an object called Ball, and I added keyboard interactivity to it(WASD to move the ball)
I need the camera to stay behind and follow the ball, but I am getting errors.
using UnityEngine;
using System.Collections;
public class ballmain : MonoBehaviour {
public bool isMoving = false;
public string direction;
public float camX;
public float camY;
public float camZ;
// Use this for initialization
void Start () {
Debug.Log("Can this run!!!");
}
// Update is called once per frame
void Update () {
camX = rigidbody.transform.position.x -=10;
camY = rigidbody.transform.position.y -=10;
camZ = rigidbody.transform.position.z;
camera.transform.position = new Vector3(camX, camY, camZ);
//followed by code that makes ball move
}
}
I get error "Assets/ballmain.cs(18,44): error CS1612: Cannot modify a value type return value of 'UnityEngine.Transform.position'. Consider storing the value in a temporary variable"
Does anyone know the answer? If I comment out the code about the camera the ball can move around.
here you go . a full code.
Simple Following
using UnityEngine;
using System.Collections;
public class Follow: MonoBehaviour {
public Transform target;
public float smooth= 5.0f;
void Update (){
transform.position = Vector3.Lerp (
transform.position, target.position,
Time.deltaTime * smooth);
}
}
Advanced Following
using UnityEngine;
using System.Collections;
public class SmoothFollowScript: MonoBehaviour {
// The target we are following
public Transform target;
// The distance in the x-z plane to the target
public int distance = 10.0;
// the height we want the camera to be above the target
public int height = 10.0;
// How much we
public heightDamping = 2.0;
public rotationDamping = 0.6;
void LateUpdate (){
// Early out if we don't have a target
if (TargetScript.russ == true){
if (!target)
return;
// Calculate the current rotation angles
wantedRotationAngle = target.eulerAngles.y;
wantedHeight = target.position.y + height;
currentRotationAngle = transform.eulerAngles.y;
currentHeight = transform.position.y;
// Damp the rotation around the y-axis
currentRotationAngle = Mathf.LerpAngle (currentRotationAngle, wantedRotationAngle, rotationDamping * Time.deltaTime);
// Damp the height
currentHeight = Mathf.Lerp (currentHeight, wantedHeight, heightDamping * Time.deltaTime);
// Convert the angle into a rotation
currentRotation = Quaternion.Euler (0, currentRotationAngle, 0);
// Set the position of the camera on the x-z plane to:
// distance meters behind the target
transform.position = target.position;
transform.position -= currentRotation * Vector3.forward * distance;
// Set the height of the camera
transform.position.y = currentHeight;
// Always look at the target
transform.LookAt (target);
}
}
}
If you just simply want to follow the target object align the position of the camera the way you want it and make the camera the child of the target object and the rest will do
Here're one script I found useful during my game development. I didn't create them so I give credit to wiki.unity3d.com for providing this amazing script.
Smooth Follow:
using UnityEngine;
using System.Collections;
public class SmoothFollow2 : MonoBehaviour {
public Transform target;
public float distance = 3.0f;
public float height = 3.0f;
public float damping = 5.0f;
public bool smoothRotation = true;
public bool followBehind = true;
public float rotationDamping = 10.0f;
void Update () {
Vector3 wantedPosition;
if(followBehind)
wantedPosition = target.TransformPoint(0, height, -distance);
else
wantedPosition = target.TransformPoint(0, height, distance);
transform.position = Vector3.Lerp (transform.position, wantedPosition, Time.deltaTime * damping);
if (smoothRotation) {
Quaternion wantedRotation = Quaternion.LookRotation(target.position - transform.position, target.up);
transform.rotation = Quaternion.Slerp (transform.rotation, wantedRotation, Time.deltaTime * rotationDamping);
}
else transform.LookAt (target, target.up);
}
}
More information about my work
Include Standard Mobile Asset to your project. It contains a SmoothFollow2D.js code in its script section. Attach this code with the gameobject and initialize public variables. This will simply do the job for you.
I found this simple and useful unity 2d camera follow script.
using UnityEngine;
using System.Collections;
public class FollowCamera : MonoBehaviour {
public float interpVelocity;
public float minDistance;
public float followDistance;
public GameObject target;
public Vector3 offset;
Vector3 targetPos;
// Use this for initialization
void Start () {
targetPos = transform.position;
}
// Update is called once per frame
void FixedUpdate () {
if (target)
{
Vector3 posNoZ = transform.position;
posNoZ.z = target.transform.position.z;
Vector3 targetDirection = (target.transform.position - posNoZ);
interpVelocity = targetDirection.magnitude * 5f;
targetPos = transform.position + (targetDirection.normalized * interpVelocity * Time.deltaTime);
transform.position = Vector3.Lerp( transform.position, targetPos + offset, 0.25f);
}
}
}
source unity2d camera follow script
The -= in these lines:
camX = rigidbody.transform.position.x -=10;
camY = rigidbody.transform.position.y -=10;
is wrong. The -= will attempt to modify the rigidbody.transform.position. You just want -.
However, as it stands, the camera won't track changes in the target's Z position, nor will it track properly if the camera is rotated. To get the correct position you need (in vectors):-
cam_pos = target_pos - dist_to_target * cam_look_at