I have 2 problems I want to get through.
1st problem. Changing X,Y,Z movement and updating it.
I have a driving mechanic in my game where if the user presses wasd the car moves. The problem is that I want the speed to be reduced from 15f to 5f when S(backwards) is pressed and held until released.
Here is my code below of my player script.
Please refer to void playerwalk() and backwards motion()
public class Move : MonoBehaviour
{
public float speed;
private Rigidbody rb;
private int count;
public Text countText;
// Use this for initialization
void Start()
{
rb = GetComponent<Rigidbody>();
count = 0;
SetCountText();
}
void playerWalk()
{
var x = Input.GetAxis("Horizontal") * Time.deltaTime * 75f;
var z = Input.GetAxis("Vertical") * Time.deltaTime * 15f;
transform.Rotate(0, x, 0);
transform.Translate(0, 0, -z);
}
void backwardMotion()
{
if (Input.GetKeyDown(KeyCode.S))
{
var z = Input.GetAxis("Vertical") * Time.deltaTime * 5f;
}
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Collectable"))
{
other.gameObject.SetActive(false);
count = count + 1;
SetCountText();
}
}
void SetCountText()
{
countText.text = "Count: " + count.ToString();
}
// Update is called once per frame
void Update ()
{
backwardMotion();
playerWalk();
}
}
This currently is not affecting anything and the void backwardsmotion() seems to have no effect.
Do I need a while loop?
What is the syntax for do until in C#?
2nd Problem : Do until loop?
To those of you who haven't seen my recent posts, I also have a flashlight mechanic on my car model where if you press L, the flashlights will turn on(toggle) and if you press S the backlights will as you reverse.
Here is my flashlight game mechanic code:
Please refer to Void switchoffLights()
public class headLights : MonoBehaviour
{
public Light frontlights;
public Light frontlights2;
public Light frontlights3;
public Light frontlights4;
public Light backlights;
public Light backlights2;
public Light backlights3;
public Light backlights4;
// Use this for initialization
void Start()
{
frontlights.enabled = !frontlights.enabled;
frontlights2.enabled = !frontlights2.enabled;
frontlights3.enabled = !frontlights3.enabled;
frontlights4.enabled = !frontlights4.enabled;
}
void switchoffLight()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.L))
{
if (frontlights && frontlights2 && frontlights3 && frontlights4 != null)
{
frontlights.enabled = !frontlights.enabled;
frontlights2.enabled = !frontlights2.enabled;
frontlights3.enabled = !frontlights3.enabled;
frontlights4.enabled = !frontlights4.enabled;
}
}
if (Input.GetKeyDown(KeyCode.S))
{
if (backlights && backlights2 && backlights3 && backlights4 != null)
{
backlights.enabled = !backlights.enabled;
backlights2.enabled = !backlights2.enabled;
backlights3.enabled = !backlights3.enabled;
backlights4.enabled = !backlights4.enabled;
}
}
}
}
However the backlights do not turn off when the S key is released.
I could not clearly understand what was going on with other codes and answers which is why I am asking here.
Thank you in advance! I am only just starting for my grade 10 programming class so please explain like you would to a younger person.
You are not applying any change to transform or rotation when pressing
if (Input.GetKeyDown(KeyCode.S))
{var z = Input.GetAxis("Vertical") * Time.deltaTime * 5f;
}
// Where this z go ?????
// Add this or whatever you want "transform.Translate(0, 0, -z);"
For Second question Use GetKeyUp() in another condition or use getkey in same condition
For the first question, you declared var z twice but they are actually individual values.
var z = Input.GetAxis("Vertical") * Time.deltaTime * 15f; // playerWalk()
and
var z = Input.GetAxis("Vertical") * Time.deltaTime * 5f; // backwardMotion()
refer to two different variables with the same name z but each only live in the method it is declared in. The z in playerWalk() and the z in backwardMotion() has nothing to do with each other. The z in backwardMotion() essentially serves no purpose as the variable is declared but never used anywhere in the method.
The correct way to achieve what you want will be:
void playerWalk()
{
var x = Input.GetAxis("Horizontal") * Time.deltaTime * 75f;
var z = Input.GetAxis("Vertical") * Time.deltaTime * 15f;
if (Input.GetKeyDown(KeyCode.S))
{
// If "S" is pressed, the z speed would be reduced to 5f.
z = Input.GetAxis("Vertical") * Time.deltaTime * 5f;
}
transform.Rotate(0, x, 0);
transform.Translate(0, 0, -z);
}
For the second question, there are three way to get input: Input.GetKeyDown, Input.GetKey and Input.GetKeyUp.
Input.GetKeyDown is called only once on the frame you pressed the key.
Input.GetKey is called every frame the key is held down.
Input.GetKeyUp is called only once on the frame you released the key.
In your case, your car backlight would be turned on when it detects a Input.GetKeyDown(KeyCode.S) but nothing lets it turn back off when it detects a release.
The solution would be to simply check for a release and turn off the headlight:
if (Input.GetKeyUp(KeyCode.S)) // Detects a release of "S" key
{
if (backlights && backlights2 && backlights3 && backlights4)
{
backlights.enabled = false;
backlights2.enabled = false;
backlights3.enabled = false;
backlights4.enabled = false;
}
}
Related
Hello I'm a newbie and I have an error I searched google and there came up results but they used to work I remember but I guess it updated anyway whenever I write this:
m_Rigidbody.velocity.magnitude = m_Max_SpeedBACK;
(Yes, I didn't forget to make the float itself)
And it shows this error
enter image description here
It said I'm not allowed to send img but anyway I want to have this if written simply
(rb.speed = float)
Can anyone help, thanks?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class my_Char_Cont : MonoBehaviour
{
public Rigidbody m_Rigidbody;
public float m_Thrust_Forth = 20f;
public float m_Thrust_Behind = -20f;
public float m_time = 10f;
public float m_timeNeg = -10f;
public float m_Max_SpeedFORTH = 4f;
public float m_Max_SpeedBACK = 2f;
// Start is called before the first frame update
void Start()
{
m_Rigidbody = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
bool forwardPress = Input.GetKey("w");
bool backPress = Input.GetKey("s");
bool leftShiftPress = Input.GetKey("left shift");
//---------------------------------------------------------------------------------------------------//
if (forwardPress)
{
m_time = m_time + Time.deltaTime;
if (m_time >= 4)
{
m_time = 3.9f;
}
m_Rigidbody.AddForce(transform.forward * m_Thrust_Forth * m_time);
}
else
{
m_time = 0;
}
if (backPress)
{
m_timeNeg = m_timeNeg + Time.deltaTime;
if (m_timeNeg >= 4)
{
m_timeNeg = 3.9f;
}
m_Rigidbody.AddForce(transform.forward * m_Thrust_Behind * m_timeNeg);
if (m_Rigidbody.velocity.magnitude >= m_Max_SpeedBACK)
{
m_Rigidbody.velocity.magnitude = m_Max_SpeedBACK;
}
}
else
{
m_timeNeg = 0;
}
}
}
The velocity can be read, but not written like that. As #Ruzihm already explained.
If you want to limit the velocity while keeping the direction, do this:
if (m_Rigidbody.velocity.magnitude >= m_Max_SpeedBACK)
{
m_Rigidbody.velocity = m_Rigidbody.velocity.normalized * m_Max_SpeedBACK;
}
normalized returns the vector, normalized so that the length (magnitude) is 1. But to clarify: it is not "(1,1,1)" - the direction stays. Example: (0.802, 0.267, 0.534) has a magnitude of 1.
Therefore, you can assign the velocity to a value, that equals the normalized velocity * your max allowed magnitude.
I'm making a ladder for my Unity game. Nothing much happens when you hover over it (that's normal). I want to freeze gravity by setting gravityscale 0 whenever the up arrow key is pressed (or w). Thankfully that works. Unfortunately though whenever I go down, gravity is still 0 but somehow my character falls back to the ground.
Here's my player code. Sorry the formatting is very bad; I just deleted the things that didn't have to do with ladders so you won't read irrelevant details.
// ladder
public float climb;
public float climbspeed;
public float gravitystore;
public bool laddered;
public GameObject laddercheck;
public float upaxis;
public xpositionladdercheck ladderx;
// Start is called before the first frame update
void Start()
{
ladderx = FindObjectOfType<xpositionladdercheck>();
jumptimecounter = Jumptime;
jumpscriptbetter = FindObjectOfType<BetterJump>();
gameover = false;
respawnscreen = FindObjectOfType<RespawnIntermission>();
lives = 5;
atkindex = FindObjectOfType<attackindex>();
scale =transform.localScale;
basicattackscript = FindObjectOfType<BasicAttack>();
basicattacksupply = 0;
rb = GetComponent<Rigidbody2D>();
gravitystore = rb.gravityScale;
}
// Update is called once per frame
private void Update()
{
horimove = Input.GetAxis("Horizontal");
if (isDead == false)
{
upaxis = Input.GetAxis("Vertical");
anim.SetFloat("run", Mathf.Abs(horimove));
if (Input.GetKeyDown(KeyCode.Space) && laddered)
{
jumpladder();
}
anim.SetFloat("run", Mathf.Abs(horimove));
if (laddered && Mathf.Abs(upaxis) > .01)
{
rb.gravityScale = 0;
climbm();
} else if (!laddered)
{
rb.gravityScale = gravitystore;
}
if (laddered&&Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine("jumpable");
}
rb.velocity = new Vector2(speed * horimove * Time.fixedDeltaTime, rb.velocity.y);
if (Input.GetKey(KeyCode.Space) && OnGround)
{
jump();
}
}
}
IEnumerator jumpable()
{
laddercheck.SetActive(false);
yield return new WaitForSeconds(.8f);
laddercheck.SetActive(true);
}
void climbm()
{
if (laddered)
{
if (upaxis > .1f) {
} else if (!laddered)
{
rb.constraints = RigidbodyConstraints2D.FreezeRotation;
}
rb.velocity = Vector2.up * climbspeed * upaxis *Time.deltaTime;
transform.position = new Vector2(ladderx.ladderxpos, rb.position.y);
// the ladder.x things is just a script that gets the x position of the ladder but it works well so ignore that.
}
}
public void jump()
{
}public void jumpladder()
{
if (Input.GetKeyDown(KeyCode.Space))
{
rb.AddForce(Vector2.up * jumpforce * Time.fixedDeltaTime);
}
}
}
}
I set mass to the lowest (.0001) and still the same thing happens. I didn't include the ladderx position script or the sensing that I'm even on a ladder script but that's irrelevant to the question. It senses everything just fine and the xposition script works well as well.
I figured it out. For some reason I had to set the Physics2D.gravity to new Vector2 (0,0); whenever I climb the ladder. Then I made a vector 2 physgravity variable that stores the natural gravity and set it back to that whenever I leave the ladder.
public Vector2 physgravity;
physgravity = Physics2D.gravity;
Physics2D.gravity = new Vector2(0f, -9.81f);
private void Update()
{
if (!laddered)
{
Physics2D.gravity = new Vector2(0f, -9.81f);
}
____________________ (later on in the script)
if (laddered && Mathf.Abs(upaxis) > .01)
{
rb.gravityScale = 0;
Physics2D.gravity = new Vector2(0, 0);
rb.velocity = new Vector2(0, 0);
climbm();
I created a multiplayer game with pun2 (Photon Unity Networking) but when I move and look actually changes of my character will apply to other characters, also when my friends move their changes will apply to my character
void Update(){
isGrounded = Physic.CheckSqhere(groundCheck.position,groundDistance, LayeMask);
if (isGrounded && velocity.y<0)
{
velocity.y=-1f;
}
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
if (Input.GetButtonDown("Jump") && isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
Vector3 Movement = transform.right * x * transform.forward *z;
if (isGrounded)
{
characterController.Move(Movement * speed * Time.deltaTime)
}
else{
characterController.Move(Movement * speedOnJumping * Time.deltaTime)
}
velocity.y +=gravity * Time.deltaTime;
characterController.Move(velocity * Time.deltaTime);}
and
void Start(){
PhotonNetwork.ConnectUsingsettings();
}
public override void onConnectedToMaster(){
PhotonNetwork. AutomaticallySyncScene = true;
createButton.onclick.AddListener(()=>{
PhotonNetwork.createRoom("Amin's Room");
});
joinButton.onclick.AddListener(()=>{
PhotonNetwork.JoinRoom("Amin'sRoom");
});
base.OnConnectedToMaster();
}
public override void OnJoinedRoom(){
if (PhotonNetwork.IsMasterClient){
Debug.Log("you are the master");
PhotonNetwork.LoadLevel(1);
}
base.OnJoined Room();
}
For the future: Please add code as TEXT not as images to your questions!
In your Update method you listen to global keyboard events. These will be executed on all instances of that script.
You should check if the component actually belongs to your own player and otherwise ignore it or even better disable the entire component!
See Photon User Input Management
// Note that inheriting from MonoBehaviourPun instead of MonoBehaviour is mandatory!
public class YourClass : MonoBehaviourPun
{
...
private void Update()
{
// As also described in the link the IsConnected is checked in order to allow
// offline debugging of your behavior without being in a network session
if(PhotonNetwork.IsConnected && !photonView.IsMine)
{
// optional but why keep an Update method running of a script that
// shall anyway only be handled by the local player?
//enabled = false;
// Or you could even remove the entire component
//Destroy(this);
// Do nothing else
return;
}
...
}
}
The script is supposed to allow my first person controller/player go up to an object, press the E key and then pickup and carry the object around. There are errors in the script and I don't understand how to program yet. I've also attached the screenshot of the errors in the code for reference.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PickupObject : MonoBehaviour
{
GameObject mainCamera;
bool carrying;
GameObject carriedObject;
public float distance;
public float smooth;
// Start is called before the first frame update
void Start()
{
mainCamera = GameObject.FindWithTag("MainCamera");
}
// Update is called once per frame
void Update()
{
if (carrying)
{
carry(carriedObject);
checkDrop();
}
else
{
pickup();
}
}
void carry(GameObject o)
{
o.GetComponent<Rigidbody>().isKinematic = true;
o.transform.position = Vector3.Lerp (mainCamera.transform.position + mainCamera.transform.forward * distance, Time.deltaTime * smooth);
}
void pickup()
{
if (Input.GetKeyDown KeyCode.E;))
{
int x = Screen.width / 2;
int y = Screen.height / 2;
}
Ray ray = mainCamera.GetComponent<Camera>().ScreentPointToRay(new Vector3(x, y));
RaycastHit hit;
if(Physics.Raycast(ray, out hit))
{
Pickupable p = hit.collider.GetComponent<Pickupable>();
if(p != null)
{
carrying = true;
carriedObject = p.gameObject;
p.gameObject.rigidbody.isKinematic = true;
}
}
}
}
void checkDrop()
{
if(Input.GetKeyDown(KeyCode.E))
{
dropObject();
}
void dropObject()
{
carrying = false;
carriedObject = null;
carriedObject.gameObject.rigidbody.isKinematic = false;
}
}
}
Maybe you should try using Raycasts to pickup items. Create a "Pick Up" tag, add that tag to all pickup-able items, shoot a Raycast from the camera in the direction of the camera if the player presses 'E', check if the hit has the tag, then pick it up. Search up "Raycast tutorial" and you will find many results.
Within pickup you define int x and int y inside of an if block.
The second issue is that within (or after) the pickup method you have one closing } to much.
if (Input.GetKeyDown KeyCode.E;))
{
int x = Screen.width / 2;
int y = Screen.height / 2;
} // <-- SEEMS THAT THIS HERE IS YOUR PROBLEM !
So you basically end your class before the method checkDrop. The rest are just follow up errors: The x and y will be known only within this code block and when you later try to use them in
Ray ray = mainCamera.GetComponent<Camera>().ScreentPointToRay(new Vector3(x, y));
they do not exist.
Also as said you and the class so the method checkDrop is not known in Update. And then you get some additional errors anyway since it is not allowed to define a method outside of a type.
Note that I formatted your code so it should be quite clear now. You probably rather wanted it do to be
void pickup()
{
if (Input.GetKeyDown KeyCode.E;))
{
int x = Screen.width / 2;
int y = Screen.height / 2;
Ray ray = mainCamera.GetComponent<Camera>().ScreentPointToRay(new Vector3(x, y));
RaycastHit hit;
if(Physics.Raycast(ray, out hit))
{
Pickupable p = hit.collider.GetComponent<Pickupable>();
if(p != null)
{
carrying = true;
carriedObject = p.gameObject;
p.gameObject.rigidbody.isKinematic = true;
}
}
}
}
In one of my games, a snake like, I have a bug where the parts are supposed to be 0.125f apart, but instead, the the distance between is the same as the distance between the first and second part.
What I believe to be the relevant code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class SnakeHead : MonoBehaviour
{
public float growTime = 5;
private float moveSpeed;
private Transform origin, prevPart = null;
private List<GameObject> snakeBodyPartsList;
public Mesh mesh;
public Material material;
private GameObject body, sphere;
private RaycastHit hit;
void Start()
{
sphere = GameObject.Find("Sphere");
origin = new GameObject("SnakeHead Origin").transform;
origin.parent = sphere.transform;
transform.parent = origin;
snakeBodyPartsList = new List<GameObject>();
snakeBodyPartsList.Add(gameObject);
StartCoroutine("addBodyPart");
}
void Update()
{
if (Input.GetKey(KeyCode.Escape))
{
Application.Quit();
}
foreach (GameObject part in snakeBodyPartsList)
{
moveSpeed = 30 + (snakeBodyPartsList.Count * 2.5f);
if (part == gameObject)
{
if (Input.GetKey("a") || Input.GetKey("d"))
{
var turnRate = Input.GetKey("a") ? -120 : 120;
part.transform.parent.Rotate(0, 0, turnRate * Time.deltaTime);
}
part.transform.rotation = Quaternion.LookRotation(transform.forward, part.transform.position - sphere.transform.position);
part.transform.parent.rotation = Quaternion.AngleAxis(moveSpeed * Time.deltaTime, Vector3.Cross(part.transform.parent.position - part.transform.position, part.transform.forward)) * part.transform.parent.rotation;
}
else
{
part.transform.rotation = Quaternion.LookRotation(prevPart.transform.position, part.transform.position - sphere.transform.position);
if (prevPart != null && Vector3.Distance(part.transform.position, prevPart.position) > 0.125f)
{
// moveSpeed = moveSpeed + Vector3.Distance(part.transform.position, prevPart.position)* 100;
part.transform.parent.rotation = Quaternion.AngleAxis(moveSpeed * Time.deltaTime, Vector3.Cross(part.transform.parent.position - part.transform.position, -(prevPart.position - part.transform.position).normalized * 0.125f)) * part.transform.parent.rotation;
}
}
returnToSurface(part);
prevPart = part.transform;
}
}
private IEnumerator addBodyPart()
{
yield return new WaitForSeconds(1);
body = createNewGameObject(body, "Body " + snakeBodyPartsList.Count, null, mesh, material, snakeBodyPartsList[snakeBodyPartsList.Count - 1].transform.position, Vector3.one / 10, true, true);
snakeBodyPartsList.Add(body);
yield return new WaitForSeconds(Mathf.Abs(growTime - 1));
StartCoroutine("addBodyPart");
}
public GameObject createNewGameObject(GameObject uGO, string Name, Transform Parent, Mesh Mesh, Material Material, Vector3 Position, Vector3 localScale, bool needsOrigin, bool needscollider)
{
uGO = new GameObject(Name);
if (needsOrigin)
{
origin = new GameObject("BodyPart Origin " + snakeBodyPartsList.Count).transform;
origin.parent = sphere.transform;
uGO.transform.parent = origin;
}
else
{
uGO.transform.parent = Parent;
}
uGO.gameObject.AddComponent<MeshFilter>().mesh = Mesh;
uGO.AddComponent<MeshRenderer>().material = Material;
uGO.transform.position = Position;
uGO.transform.localScale = localScale;
if (needscollider)
{
uGO.AddComponent<BoxCollider>().size = Vector3.one;
uGO.GetComponent<BoxCollider>().isTrigger = true;
}
uGO.transform.forward = transform.forward;
uGO.transform.rotation = transform.rotation;
return uGO;
}
void returnToSurface(GameObject a)
{
if (Vector3.Distance(a.transform.position, sphere.transform.position) > 1.05)
{
while (Vector3.Distance(a.transform.position, sphere.transform.position) >= 1.045)
{
a.transform.position = new Vector3(a.transform.position.x, a.transform.position.y, a.transform.position.z - 0.001f);
}
}
else if (Vector3.Distance(a.transform.position, sphere.transform.position) < 1.04)
{
while (Vector3.Distance(a.transform.position, sphere.transform.position) <= 1.045)
{
a.transform.position = new Vector3(a.transform.position.x, a.transform.position.y, a.transform.position.z + 0.001f);
}
}
}
public List<GameObject> getPartsList()
{
return snakeBodyPartsList;
}
}
The movement of the block is probably badly coded because I am fairly new, any general tips and cleanup is generally welcome also. The blocks are moving around a sphere hence the perhaps odd seeming movement code.
I might be wrong about this, but I don't have enough rep to comment, so I'll post it as a reply for you to try:
Since your issue is only between the head and first body part, I'm imagining your issue is because there's no prevPart set on the first run (the gameObject body part isn't necessarily the first one to be checked in the foreach). You might want to try handling the first if-statement before the foreach, so that everything is guaranteed to be set up properly for the first run. You can keep the gameObject body part out of the list or handle the case with an if (like in this example).
Something like this:
void Update()
{
moveSpeed = 30 + (snakeBodyPartsList.Count * 2.5f);
// First update the head (gameObject)
if (Input.GetKey("a") || Input.GetKey("d"))
{
var turnRate = Input.GetKey("a") ? -120 : 120;
transform.parent.Rotate(0, 0, turnRate * Time.deltaTime);
}
transform.rotation = Quaternion.LookRotation(transform.forward, transform.position - sphere.transform.position);
transform.parent.rotation = Quaternion.AngleAxis(moveSpeed * Time.deltaTime, Vector3.Cross(transform.parent.position - transform.position, transform.forward)) * transform.parent.rotation;
returnToSurface(part);
prevPart = part.transform;
// Then update the body (snakeBodyPartsList)
foreach (GameObject part in snakeBodyPartsList)
{
if (part != gameObject)
{
if (prevPart != null) // prevPart is already used here, so you might as well check it here instead of after the next line
{
part.transform.rotation = Quaternion.LookRotation(prevPart.transform.position, part.transform.position - sphere.transform.position);
if (Vector3.Distance(part.transform.position, prevPart.position) > 0.125f)
{
part.transform.parent.rotation = Quaternion.AngleAxis(moveSpeed * Time.deltaTime, Vector3.Cross(part.transform.parent.position - part.transform.position, -(prevPart.position - part.transform.position).normalized * 0.125f)) * part.transform.parent.rotation;
}
}
else
{
Debug.Log('No prevPart in the snakeBodyPartsList foreach'); // EDIT: Might as well add something here just in case... :)
}
returnToSurface(part);
prevPart = part.transform;
}
}
}
Does that help?
PS: The movement code looks fine to me, but you might want to give your magic numbers variable names for clarity.
So, this was solved by halving the move speed of the head during turning, havnt figure out why but the head moves faster than the body when turning causing it to pull away from the body parts. Thanks #Bruins from solent uni.