in unity i made a script for my guy to crouch, run , and have his regular speed but when i crouch i just fall forever into the terrain was wondering if it is my code or i have to put a check on the terrain.
var walkSpeed: float = 7; // regular speed
var crchSpeed: float = 3; // crouching speed
var runSpeed: float = 20; // run speed
private var chMotor: CharacterMotor;
private var ch: CharacterController;
private var tr: Transform;
private var height: float; // initial height
function Start(){
chMotor = GetComponent(CharacterMotor);
tr = transform;
ch = GetComponent(CharacterController);
height = ch.height;
}
function Update(){
var h = height;
var speed = walkSpeed;
if (ch.isGrounded && Input.GetKey("left shift") || Input.GetKey("right shift")){
speed = runSpeed;
}
if (Input.GetKey("c")){ // press C to crouch
h = 0.5 * height;
speed = crchSpeed; // slow down when crouching
}
chMotor.movement.maxForwardSpeed = speed; // set max speed
var lastHeight = ch.height; // crouch/stand up smoothly
ch.height = Mathf.Lerp(ch.height, h, 5*Time.deltaTime);
tr.position.y += (ch.height-lastHeight)/2; // fix vertical position
}
This line could be responsible:
tr.position.y += (ch.height-lastHeight)/2;
you might want to let gravity take care of this or add a downward Force here. Changing the transform directly makes the Object dont care about colliders in the way.
edit: a better way would probably be to change the CharacterController though, as "falling down" when crouching doesnt make much sense. Maybe you dont even need this? The way i would implement this is the root at the feet, and height goes upwards from there.
Related
So i'm currently making a game, and i've recently added a level editor, but the placing tool does not work how i wanted it to.
https://youtu.be/MuUvnVTL6eg
If you've watched this video, you've probably realized that the block placing works pretty much how placing rectangles in ms pain with alt does, and i want it to work like placing rectangles in ms pain without alt xd.
I'm using this code to place the block:
if (Input.GetKeyDown(KeyCode.Mouse0)){
startDrawPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
tmpObj = spawnObject(blocks[selected].gameObject, startDrawPos);
drawing = true;
}
if (Input.GetKey(KeyCode.Mouse0)){
Vector2 mPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 tmpScale = new Vector2(startDrawPos.x - mPos.x, startDrawPos.y - mPos.y);
tmpObj.transform.localScale = tmpScale;
}
if (Input.GetKeyUp(KeyCode.Mouse0))
{
drawing = false;
var scale = tmpObj.transform.localScale;
//Code below destroys the object if it's too small to avoid accidental placements
if (scale.x <= 0.1 && scale.x > -0.1 || scale.y <= 0.1 && scale.y > -0.1)
{
Destroy(tmpObj);
}
}
(All of this code is in the Update() function)
(spawnObject function just instantiates the object prefab)
There is a bit more code but it has nothing to do with the position of the block, it just detect which block is selected and decides if it can be resized or not.
I solved this problem. But because your complete script is not in question, I rebuilt the code with IEnumerator, Here, by pressing the left mouse button, IEnumerator is activated and all commands are grouped in one method to make the code more efficient.
private void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse0)) StartCoroutine(DrawRect());
}
How does the Desktop Rect formula work?
By running IEnumerator, the code first records the starting point of the mouse. It also makes a simple cube because I do not have access to your objects. Now until the mouse is pressed. Resize Rect to the difference between current and recorded points. The only thing is that to avoid ALT control, you have to place it between the current and initial points. The reason for adding the camera forward is to be seen in the camera.
cubeObject.transform.position = (startDrawPos + currentDrawPos) / 2;
The final structure of the DrawRect is as follows:
public IEnumerator DrawRect()
{
drawing = true;
var scale = Vector2.zero;
var startDrawPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
var cubeObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
while (Input.GetKey(KeyCode.Mouse0))
{
var currentDrawPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
cubeObject.transform.position = (startDrawPos + currentDrawPos) / 2 + Camera.main.transform.forward * 10;
scale = new Vector2(startDrawPos.x - currentDrawPos.x, startDrawPos.y - currentDrawPos.y);
cubeObject.transform.localScale = scale;
yield return new WaitForEndOfFrame();
}
if (scale.x <= 0.1 && scale.x > -0.1 || scale.y <= 0.1 && scale.y > -0.1) Destroy(cubeObject);
drawing = false;
}
Ok, I got a series of cards that will move 1 by 1 to the center of the camera each and every time the user clicks.
StageContainer is the parent of all cards. This is the one that will move making it look like the cards are moving instead.
First I this is my code without smoothdamp
// Update is called once per frame
void Update () {
if(Input.GetMouseButtonDown(0)){
StartCoroutine ( ProcessFocus() );
frames++;
}
}
IEnumerator ProcessFocus() {
curPos = StageContainer.transform.localPosition;
nextPos = curPos;
nextPosX = nextPos.x - 400;
nextPos.x = nextPosX;
StageContainer.transform.localPosition = nextPos;
yield break;
}
The code above gives me the instant change of cards on the center of the camera. No transitions, animation whatsoever.. the point is it works.
Now when I change this :
StageContainer.transform.localPosition = nextPos;
to this :
float smoothTime = 0.3F;
Vector3 velocity = Vector3.zero;
StageContainer.transform.localPosition = Vector3.SmoothDamp(curPos, nextPos, ref velocity, smoothTime);
I assumed it will transition from current X point to next X point,
but every time I mouse click, it just move bit by bit like 10~20 X points
I have no clue why it behave like that. Please help.
Your coroutine needs to keep running until your movement is completed.
IEnumerator ProcessFocus() {
curPos = StageContainer.transform.localPosition;
nextPos = curPos;
nextPosX = nextPos.x - 400;
nextPos.x = nextPosX;
float smoothTime = 0.3F;
Vector3 velocity = Vector3.zero;
while(this.transform.position != nextPos) {
StageContainer.transform.localPosition = Vector3.SmoothDamp(curPos, nextPos, ref velocity, smoothTime);
yield return null;
}
}
That's because your code runs once and then exits the coroutine. To run the coroutine for some amount of time, you have to yield return some YieldInstruction instances. In this case, I suspect that you want to use WaitForEndOfFrame.
I've applied this standard assets script to my camera for a 2D game and it's actually doing a good job but since my background texture is placed inside a quad that "follows" the player and not the camera at higher movement speed the camera gets too far or too much behind the player and gets out of view.
Since I never programmed in JS I'd like to ask you how should I tweak this code to stop the script from moving the camera if the velocity is over (for example) 5f.
I tried to change it this way :
var target : Transform;
var smoothTime = 0.3;
private var thisTransform : Transform;
private var velocity : Vector2;
function Start()
{
thisTransform = transform;
}
function Update()
{
if(velocity.x > 5f) //in C# I'd do it this way, but apparently
velocity.x = 5f; //this is not stopping the camera from getting out of game-sight
thisTransform.position.x = Mathf.SmoothDamp( thisTransform.position.x,
target.position.x, velocity.x, smoothTime);
thisTransform.position.y = Mathf.SmoothDamp( thisTransform.position.y,
target.position.y, velocity.y, smoothTime);
}
This possibly happens because i'm actually passing a reference as a parameter (velocity.x called as a reference http://docs.unity3d.com/Documentation/ScriptReference/Mathf.SmoothDamp.html)
I am not sure if I understand you correctly.
If you want to set your camera's max speed, Mathf.SmoothDamp() can set maxSpeed.
var maxSpeed : float = 5.0f;
Mathf.SmoothDamp(transform.position.x, target.position.x, velocity.x, smoothTime, maxSpeed);
At the moment I have a script which when you hit a cube, it follows the player...but when you stand still it overlaps you. What I want is to be able to set the position of the cube to five steps behind the player at all times...how would i do this?
GameObject.Find("Cube2").transform.position = Vector3(0.5, 0.5, 0.5);
That is what I have tried so far, but that just makes the cube disappear?
the script in its entirety:
static var target : Transform; //the enemy's target
var moveSpeed = 3; //move speed
var rotationSpeed = 3; //speed of turning
var Player = GameObject.Find("Player").transform.position;
var Cube2 = GameObject.Find("Cube2").transform.position;
var myTransform : Transform; //current transform data of this enemy
function Awake()
{
//myTransform = transform; //cache transform data for easy access/preformance
}
function Start()
{
//target = GameObject.FindWithTag("Player1").transform; //target the player
}
//var distance = Vector3.Distance(Player.transform.position, Cube2.transform.position);
//Debug.Log(distance);
function Update () {
Debug.Log(Player);
//var distance = Vector3.Distance(Player.transform.position, Cube2.transform.position);
//var distance = Vector3.Distance(player_distance, cube_distance);
// if (distance > 5)
// {
if (target == GameObject.FindWithTag("Player").transform)
{
//rotate to look at the player
GameObject.Find("Cube2").transform.position = Vector3(0.5, 0.5, 0.5);
myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);
//move towards the player
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
//}
}
Like I said, I don't know unity really (had a 5 minute play with it)
In honesty it looks like you've pretty much got it - not sure why you can't get it working:
This is what should work: (assuming the quarternion calls are correct) - this is using latest Unity reference from the site so it might be diff to what works for you (what version of Unity you on?)
// Params
var moveSpeed = 3; // Move speed
var rotationSpeed = 3; // Speed of turning
// Find game objects
var Player = GameObject.Find("Player");
var Cube2 = GameObject.Find("Cube2");
function Update ()
{
// Vector from cube pos to player pos (vector math: target - position = vector to target from pos)
var dir = Player.transform.position - Cube2.transform.position;
// If the distance is over 5 units
if(dir.magnitude > 5.0f)
{
// Rotate towards player
Cube2.transform.rotation = Quaternion.Slerp(Cube2.transform.rotation, Quaternion.LookRotation(dir), rotationSpeed * Time.deltaTime);
// Move forward at specified speed
Cube2.transform.position += Cube2.transform.forward * moveSpeed * Time.deltaTime;
}
}
That should do it - if not let me know what happens (or if you get compilation errors) - like I said I don't really know Unity but I've had a look and I'm familiar with 3D/game programming
Hello i followed a tutorial on how to make a top down shooter, the code makes so that my character rotates against my mouse and i can move forward and backwards using W and S. However i also want to be able to move right and left using A and D im not good when it comes to code in javascript nor unity3d i do most of my coding in c#. And the guy that made the tutorial explained poorly what some of the code actually do.
Here is the code:
#pragma strict
var speed : float = 20.0;
var rotateSpeed : float = 2.0;
function Update () {
var controller : CharacterController = GetComponent(CharacterController);
transform.Rotate(0,Input.GetAxis("Horizontal") * rotateSpeed,0);
var forward : Vector3 = transform.TransformDirection(Vector3.forward);
var curSpeed : float = speed * Input.GetAxis("Vertical");
controller.SimpleMove(forward * curSpeed);
var position = Input.mousePosition;
var newposition = Vector3(position.x,position.y,camera.main.transform.position.y- transform.position.y);
var lastposition = camera.main.ScreenToWorldPoint(newposition);
transform.LookAt(lastposition);
}
#script RequireComponent(CharacterController)
code for staffing (moving left and right without turning)
if(Input.GetKeyUp("d")){
controller.SimpleMove(right * staffingSpeed);
}
else if(Input.GetKeyUp("a")) {
controller.SimpleMove(-right * staffingSpeed);
}
write the code in update() function and make a variable "staffingSpeed" outside the function and set it from inspector
or
replace "staffingSpeed" with a constant numeric value e.g 5