The mechanics are set up so that when the user input ("Fire1") the distance is updated and health is deducted if the distance that the raycast found is less than or equal to 1.5.
However when I click the mouse button the distance variable is not updated thus nor is the health.
**
Melee System Code
**
#pragma strict
var Damage : int = 50;
var Distance : float;
var MaxDistance : float = 1.5;
function update ()
{
if(Input.GetButtonDown("Fire1"))
{
var hit : RaycastHit;
if (Physics.Raycast (transform.position, transform.TransformDirection(Vector3.forward), hit))
{
Distance = hit.distance;
if(Distance < MaxDistance)
{
hit.transform.SendMessage("Apply Damage", Damage, SendMessageOptions.DontRequireReceiver);
}
}
}
}
Enemy Logic Code
#pragma strict
var Health : int = 100;
function ApplyDamage(Damage : int)
{
Health -= Damage;
}
*
Please Explain All Changes.
*
Other than the solution suggested by Man of Snow (certainly correct), another error is the lower-cased "u" in the update() function. The real function that you wanna call is Update() (with the upper-cased "U"). "update()" is a function that's actually never called, not the one invoked each frame by Unity.
Related
I have an automatic rigidbody car that is supposed to follow a set of waypoints on a mesh collider map but will get caught on any random waypoint and will rotate about that waypoint. Here is my code for the automatic car:
public class FollowThePath : MonoBehaviour
{
public Transform[] target;
public float speed;
public float damping = 6.0f;
public GameObject centerOfMass;
private int current;
void Start()
{
GetComponent<Rigidbody>().centerOfMass = centerOfMass.transform.localPosition;
}
void Update()
{
if (transform.position != target[current].position)
{
Vector3 pos = Vector3.MoveTowards(transform.position, target[current].position, speed * Time.deltaTime);
GetComponent<Rigidbody>().MovePosition(pos);
var rotation = Quaternion.LookRotation(target[current].position - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping);
}
else current = (current + 1) % target.Length;
}
}
I increased the mass, added a center of mass, froze the y axis position and rotation, lowered the center of mass. I noticed that the car gets stuck particularly, but not limited to curves.
Comparing two Vector3s for equality is generally a bad idea when handling moving objects.
Firstly because they use float internally, which always run the risk of being imprecise.
Secondly because Unity knows this and approximates the equality of two vectors internally. The problem is, that you don't have control over the precision being used by unity. When you implement it yourself like the function below it should be easier for you to figure out if that's the problem.
What's most likely the case is, that if (transform.position != target[current].position) never evaluates to false, since transform.position is (0,0,0) and target[current].position is (0.00000000001,0,0) or something. They are almost equal, but not quite equal, at least using the == operator. Then your code in else is never executed.
You can try something like this, where allowedDifference should be in the scope of 0.0001 for ~0.1m precision, or 0.00000001 for ~0.1mm precision:
public bool ApproximatelyEquals(Vector3 a, Vector3 b, float allowedDifference = 0.00000001f){
return Vector3.SqrMagnitude(a - b) < allowedDifference;
}
//Edit:
To clarify, use it like:
if(!ApproximatelyEquals(transform.position, target[current].position), 0.00000001f)
The code I am using currently makes the enemy notice me at a distance then follow me if I get closer. The issue I am having is with how they move. I am building a Minecraft style game but I cant get the enemies to stay on the ground and jump up each block like I have too with the fps controller. They just seem to float the shortest distance possible towards me.
Code:
var target : Transform; //the enemy's target
var moveSpeed = 3; //move speed
var rotationSpeed = 3; //speed of turning
var range : float=10f;
var range2 : float=10f;
var stop : float=0;
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("1Player").transform; //target the player
}
function Update () {
//rotate to look at the player
var distance = Vector3.Distance(myTransform.position, target.position);
if (distance<=range2 && distance>=range){
myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);
}
else if(distance<=range && distance>stop){
//move towards the player
myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);
myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;
}
else if (distance<=stop) {
myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
Quaternion.LookRotation(target.position - myTransform.position), rotationSpeed*Time.deltaTime);
}
}
Okay now here is what you are missing:
1.Lock the rotation on x and z axis to zero
myTransform.eulerAngles = new Vector3(0f, myTransform.eulerAngles.y, 0);
Just add this line at the end.
2.Make a short distance raycast in front of the AI and if it detects some obstacle, stop the current movement and move by y axis, if there is no obstacle move like you wrote in your script.
As for the raycasting goes, there is no need for me to write it here, you can find more info about it in Unity3D documentation here:
http://docs.unity3d.com/ScriptReference/Physics.Raycast.html and this tutorial is good for staters: https://unity3d.com/learn/tutorials/modules/beginner/physics/raycasting
I am developing my first game with the Unity3D engine and I have run into my first problem! Not as exciting as I thought. If I spam the jump button w my ball jumps the first time then when it lands it does not jump right away but it jumps randomly after a number of button presses. The code I am using is below.
#pragma strict
var rotationSpeed = 100;
var jumpHeight = 8;
private var isFalling = false;
function Update ()
{
//Handle ball rotation.
var rotation : float = Input.GetAxis ("Horizontal") * rotationSpeed;
rotation *= Time.deltaTime;
rigidbody.AddRelativeTorque (Vector3.back * rotation);
if (Input.GetKeyDown(KeyCode.W) && isFalling == false)
{
rigidbody.velocity.y = jumpHeight;
}
isFalling = true;
}
function OnCollisionStay ()
{
isFalling = false;
}
I heard this was a arithmetic behavior problem in UnityScript. I am a very beginner at programming and do not really understand the code in UnityScript and this is the first game/project I am making in Unity3D. Help would be greatly appreciated. Thanks!
You would think that something as simple as jumping should be a no-brainer, but there are a couple of gotchas here:
It can happen that Update() is called twice without any physics updates in between. This means you don't receive OnColliderEnter nor OnColliderStay in between but you still reset isFalling, blocking the jump key.
The moment the ball hits you will receive OnColliderEnter, but not OnColliderStay. This won't happen until the next physics update. If you only listen to -stay you will be one update late.
If you press jump right at the time the ball is supposed to hit the ground then your key is already down when the first collider hit registers. You will be another update late.
Objects sink a little bit into the collider. When you jump, it might take a couple of updates before you clear the collider and you will receive OnColliderStay after you jumped.
I think that last point is the biggest problem here. To solve this you need to do a couple of things:
Use both OnColliderEnter and OnColliderStay. This will imrpove your timing with one update.
Reset isFalling in FixedUpdate instead of in Update. FixedUpdate is part of the physics loop, so it is called right before OnCollisionEnter and OnCollisionStay who will set it again immediately if needed.
Remember that you are trying to jump until you are actually in the air. This allows you to clear the collider with one button press.
The code below implements these points. If you want the timing to be even tighter you must queue the next jump while you are in the air.
#pragma strict
var rotationSpeed = 100;
var jumpHeight = 8;
private var isFalling = false;
private var tryingToJump = false;
function Update ()
{
//Handle ball rotation.
var rotation : float = Input.GetAxis ("Horizontal") * rotationSpeed;
rotation *= Time.deltaTime;
rigidbody.AddRelativeTorque (Vector3.back * rotation);
if (Input.GetKeyDown(KeyCode.W) && !isFalling) tryingToJump = true;
if (tryingToJump)
{
if (isFalling) tryingToJump = false;
else rigidbody.velocity.y = jumpHeight;
}
}
function FixedUpdate()
{
isFalling = true;
}
function OnCollisionStay()
{
isFalling = false;
}
function OnCollisionEnter()
{
isFalling = false;
}
I'm following a tutorial into making a game in Unity, and I've encountered a peculiar problem with my JavaScript/UnityScript:
#pragma strict
var Health = 100;
function ApplyDamage (TheDamage : int)
{
Health -= TheDamage;
if(Health <= 0)
{
Dead();
}
}
function Dead()
{
Destroy (gameObject);
}
That is my script for the enemy game object, however, despite me having logic for a melee system where you have to click him twice and he dies, it doesn't work, and whenever my player character walks into the enemy it is destroyed automatically without clicks.
I'll post my melee system here too:
#pragma strict
var TheDamage : int = 50;
var Distance : float;
var MaxDistance : float = 1.5;
function Update ()
{
if (Input.GetButtonDown("Fire1"))
var hit : RaycastHit;
if (Physics.Raycast (transform.position, transform.TransformDirection(Vector3.forward), hit))
{
Distance = hit.distance;
if (Distance < MaxDistance)
(
hit.transform.SendMessage("ApplyDamage", TheDamage, SendMessageOptions. DontRequireReceiver)
);
}
}
Can anyone help me with this? It seems like a random error.
The code you posted for your melee system is missing braces {} for the first if statement, causing it to only execute var hit : RaycastHit; when the mouse is clicked, and execute the rest of the body every time Update is called.
Your code has a problem. You are not actually using the if statement correctly. This is because you didn't use {}. I will post how your code is being interpreted below:
if (Input.GetButtonDown("Fire1"))
{
var hit : RaycastHit;
}
if (Physics.Raycast (transform.position, transform.TransformDirection(Vector3.forward), hit))
{
Distance = hit.distance;
if (Distance < MaxDistance)
{
hit.transform.SendMessage("ApplyDamage", TheDamage, SendMessageOptions. DontRequireReceiver);
}
}
Obviously that is not what you intended. Remember if you don't put the brackets then only the line directly after the if will execute when the if condition is met, the rest will execute independently of that if.
Solution
if (Input.GetButtonDown("Fire1"))
{
var hit : RaycastHit;
if (Physics.Raycast (transform.position, transform.TransformDirection(Vector3.forward), hit))
{
Distance = hit.distance;
// Intentionally left the brackets out of this if to show you.
if(Distance < MaxDistance)
hit.transform.SendMessage("ApplyDamage", TheDamage, SendMessageOptions. DontRequireReceiver);
}
}
So I intentionally left out the brackets on that inside if to show you how to use it without brackets. If you are unsure, just add brackets, it will make your code cleaner and easier to understand and you will avoid bugs.
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