Having a bit of trouble with unity. I have had two different builds for firing and movement systems, now I am porting them together although I encounter some issues when I do this. The 'bullet' prefab in the assets folder is asked to be spawned into the game scene but never is. But what is more intriguing is the other functions of the 'bullet' and script take place, so it is only the prefab not showing in the scene.
THe following is the code from the script which instaniates the prefab:
public bool isFiring; // Boolean to check if the player is firing
public bool isReloading = false; // Boolean to check if the player is reloading
public BulletController bullet; // Reference another script
public float bulletSpeed; // bullet speed - changed in bullet controller
public float timeBetweenShots; // time between shots can be fired
private float shotCounter; // Tempoary time holder - ensures no bullet spam
public Transform firePoint; // The fire point in the game attached to the gun
public static int ammoRemaining = 3; // Ammo left for the player to fire
public static int maxAmmo = 3;
public Text ammoText;
public Rigidbody cannonballInstance;
public BulletController projectile;
[Range(10f, 80f)]
public float angle = 45f;
// Use this for initialization
void Awake () {
isReloading = false;
timeBetweenShots = 0.3f;
ammoRemaining = maxAmmo;
}
// Update is called once per frame
void Update () {
if (ammoRemaining == 0 && isReloading == false)
{
StartCoroutine(Reload());
}
else if (isFiring == true && isReloading == false)
{
shotCounter -= Time.deltaTime;
if(shotCounter <= 0 && ammoRemaining > 0 && isReloading == false)
{
shotCounter = timeBetweenShots;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo))
{
FireCannonAtPoint(hitInfo.point);
}
ammoRemaining -= 1;
ammoText.text = "Ammo:" + ammoRemaining;
}
}
else if (Input.GetKey(KeyCode.R))
{
StartCoroutine(Reload());
}
else
{
shotCounter = 0;
}
}
private void FireCannonAtPoint(Vector3 point)
{
Vector3 randomAccuracy;
randomAccuracy = new Vector3(Random.Range(-2.0f, 2f), 0, Random.Range(-2f, 2f));
var velocity = BallisticVelocity(point + randomAccuracy, angle);
Debug.Log("Firing at " + (point + randomAccuracy) + " velocity " + velocity);
Rigidbody rg = Instantiate(cannonballInstance, transform.position, transform.rotation);
Debug.Log("Firing at" + transform.position);
Debug.Log(rg.transform);
BulletController newProjectile = rg.GetComponent<BulletController>();
newProjectile.speed = velocity;
Debug.Log(newProjectile.speed);
// cannonballInstance.transform.position = transform.position ;
// cannonballInstance.velocity = velocity;
}
private Vector3 BallisticVelocity(Vector3 destination, float angle)
{
Vector3 direction = destination - transform.position; // get Target Direction
float height = direction.y; // get height difference
direction.y = 0; // retain only the horizontal difference
float distance = direction.magnitude; // get horizontal direction
float AngleRadians = angle * Mathf.Deg2Rad; // Convert angle to radians
direction.y = distance * Mathf.Tan(AngleRadians); // set direction to the elevation angle.
distance += height / Mathf.Tan(AngleRadians); // Correction for small height differences
// Calculate the velocity magnitude
float velocity = Mathf.Sqrt(distance * Physics.gravity.magnitude / Mathf.Sin(2 * AngleRadians));
Debug.Log(velocity);
return velocity * direction.normalized; // Return a normalized vector.
}
public IEnumerator Reload()
{
isReloading = true;
ammoText.text = "REL...";
yield return new WaitForSeconds(2);
ammoRemaining = maxAmmo;
isReloading = false;
ammoText.text = "Ammo:" + ammoRemaining;
}
}
Everything is the same in the two seperate version but it just the spawning in of the prefab which doesn't work.
Any ideas/suggestions are much appreciated.
From your code:
public Rigidbody cannonballInstance;
[...]
Rigidbody rg = Instantiate(cannonballInstance, transform.position, transform.rotation);
You are Instantiating a Rigidbody where I think you expect to instantiate a GameObject
try with:
Rigidbody rg = Instantiate(cannonballInstance.gameObject, transform.position, transform.rotation).GetComponent<Rigidbody>();
Related
Hi i have a scenario in which i need to limit the angle rotation for 3rd person controller.Present when i press left and right input keys it is turning 90degrees. I wish to rotate 45degrees. Could someone help me,at which line that angle rotation is happening.
Here my code :
public class ThirdPersonShooter : MonoBehaviour
{
public AnimationClip idleAnimation;
public AnimationClip walkAnimation;
public AnimationClip runAnimation;
public AnimationClip jumpPoseAnimation;
public float walkMaxAnimationSpeed = 0.75F;
public float trotMaxAnimationSpeed = 1F;
public float runMaxAnimationSpeed = 1F;
public float jumpAnimationSpeed = 1F;
public float landAnimationSpeed = 1F;
private Animation _animation;
enum CharacterState
{
Idle = 0,
Walking = 1,
Trotting = 2,
Running = 3,
Jumping = 4,
}
private CharacterState _characterState;
// The speed when walking
public float walkSpeed = 2.0F;
// after trotAfterSeconds of walking we trot with trotSpeed
public float trotSpeed = 4.0F;
// when pressing "Fire3" button (cmd) we start running
public float runSpeed = 6.0F;
public float inAirControlAcceleration = 3.0F;
// How high do we jump when pressing jump and letting go immediately
public float jumpHeight = 0.5F;
// The gravity for the character
public float gravity = 20.0F;
// The gravity in controlled descent mode
public float speedSmoothing = 10.0F;
public float rotateSpeed = 500.0F;
public float trotAfterSeconds = 3.0F;
public bool canJump = true;
private float jumpRepeatTime = 0.05F;
private float jumpTimeout = 0.15F;
private float groundedTimeout = 0.25F;
// The camera doesnt start following the target immediately but waits for a split second to avoid too much waving around.
private float lockCameraTimer = 0.0F;
// The current move direction in x-z
private Vector3 moveDirection = Vector3.zero;
// The current vertical speed
private float verticalSpeed = 0.0F;
// The current x-z move speed
private float moveSpeed = 0.0F;
// The last collision flags returned from controller.Move
private CollisionFlags collisionFlags;
// Are we jumping? (Initiated with jump button and not grounded yet)
private bool jumping = false;
private bool jumpingReachedApex = false;
// Are we moving backwards (This locks the camera to not do a 180 degree spin)
private bool movingBack = false;
// Is the user pressing any keys?
private bool isMoving = false;
// When did the user start walking (Used for going into trot after a while)
private float walkTimeStart = 0.0F;
// Last time the jump button was clicked down
private float lastJumpButtonTime = -10.0F;
// Last time we performed a jump
private float lastJumpTime = -1.0F;
// the height we jumped from (Used to determine for how long to apply extra jump power after jumping.)
private float lastJumpStartHeight = 0.0F;
private Vector3 inAirVelocity = Vector3.zero;
private float lastGroundedTime = 0.0F;
private bool isControllable = true;
// Use this for initialization
void Awake()
{
moveDirection = transform.TransformDirection(Vector3.forward);
_animation = GetComponent<Animation>();
if (!_animation)
Debug.Log("The character you would like to control doesn't have animations. Moving her might look weird.");
/*
public AnimationClip idleAnimation;
public AnimationClip walkAnimation;
public AnimationClip runAnimation;
public AnimationClip jumpPoseAnimation;
*/
if (!idleAnimation)
{
_animation = null;
Debug.Log("No idle animation found. Turning off animations.");
}
if (!walkAnimation)
{
_animation = null;
Debug.Log("No walk animation found. Turning off animations.");
}
if (!runAnimation)
{
_animation = null;
Debug.Log("No run animation found. Turning off animations.");
}
if (!jumpPoseAnimation && canJump) {
_animation = null;
Debug.Log("No jump animation found and the character has canJump enabled. Turning off animations.");
}
}
void UpdateSmoothedMovementDirection()
{
Transform cameraTransform = Camera.main.transform;
bool grounded = IsGrounded();
// Forward vector relative to the camera along the x-z plane
Vector3 forward = cameraTransform.TransformDirection(Vector3.forward);
forward.y = 0;
forward = forward.normalized;
// Right vector relative to the camera
// Always orthogonal to the forward vector
Vector3 right = new Vector3(forward.z, 0, -forward.x);
float v = Input.GetAxisRaw("Vertical");
float h = Input.GetAxisRaw("Horizontal");
// Are we moving backwards or looking backwards
if (v < -0.2f)
movingBack = true;
else
movingBack = false;
bool wasMoving = isMoving;
isMoving = Mathf.Abs(h) > 0.1f || Mathf.Abs(v) > 0.1f;
// Target direction relative to the camera
Vector3 targetDirection = h * right + v * forward;
// Grounded controls
if (grounded)
{
// Lock camera for short period when transitioning moving standing still
lockCameraTimer += Time.deltaTime;
if (isMoving != wasMoving)
lockCameraTimer = 0.0f;
// We store speed and direction seperately,
// so that when the character stands still we still have a valid forward direction
// moveDirection is always normalized, and we only update it if there is user input.
if (targetDirection != Vector3.zero)
{
// If we are really slow, just snap to the target direction
if (moveSpeed < walkSpeed * 0.9f && grounded)
{
moveDirection = targetDirection.normalized;
}
// Otherwise smoothly turn towards it
else
{
moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);
moveDirection = moveDirection.normalized;
}
}
// Smooth the speed based on the current target direction
float curSmooth = speedSmoothing * Time.deltaTime;
// Choose target speed
//* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways
float targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0f);
_characterState = CharacterState.Idle;
// Pick speed modifier
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
{
targetSpeed *= runSpeed;
_characterState = CharacterState.Running;
}
else if (Time.time - trotAfterSeconds > walkTimeStart)
{
targetSpeed *= trotSpeed;
_characterState = CharacterState.Trotting;
}
else
{
targetSpeed *= walkSpeed;
_characterState = CharacterState.Walking;
}
moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);
// Reset walk time start when we slow down
if (moveSpeed < walkSpeed * 0.3f)
walkTimeStart = Time.time;
}
// In air controls
else
{
// Lock camera while in air
if (jumping)
lockCameraTimer = 0.0f;
if (isMoving)
inAirVelocity += targetDirection.normalized * Time.deltaTime * inAirControlAcceleration;
}
}
void ApplyJumping()
{
// Prevent jumping too fast after each other
if (lastJumpTime + jumpRepeatTime > Time.time)
return;
if (IsGrounded())
{
// Jump
// - Only when pressing the button down
// - With a timeout so you can press the button slightly before landing
if (canJump && Time.time < lastJumpButtonTime + jumpTimeout) {
verticalSpeed = CalculateJumpVerticalSpeed(jumpHeight);
SendMessage("DidJump", SendMessageOptions.DontRequireReceiver);
}
}
}
void ApplyGravity()
{
if (isControllable) // don't move player at all if not controllable.
{
// Apply gravity
bool jumpButton = Input.GetButton("Jump");
// When we reach the apex of the jump we send out a message
if (jumping && !jumpingReachedApex && verticalSpeed <= 0.0f)
{
jumpingReachedApex = true;
SendMessage("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);
}
if (IsGrounded())
verticalSpeed = 0.0f;
else
verticalSpeed -= gravity * Time.deltaTime;
}
}
float CalculateJumpVerticalSpeed(float targetJumpHeight)
{
// From the jump height and gravity we deduce the upwards speed
// for the character to reach at the apex.
return Mathf.Sqrt(2 * targetJumpHeight * gravity);
}
void DidJump()
{
jumping = true;
jumpingReachedApex = false;
lastJumpTime = Time.time;
//lastJumpStartHeight = transform.position.y;
lastJumpButtonTime = -10;
_characterState = CharacterState.Jumping;
}
void Update()
{
if (!isControllable)
{
// kill all inputs if not controllable.
Input.ResetInputAxes();
}
if (Input.GetButtonDown("Jump"))
{
lastJumpButtonTime = Time.time;
}
UpdateSmoothedMovementDirection();
// Apply gravity
// - extra power jump modifies gravity
// - controlledDescent mode modifies gravity
ApplyGravity();
// Apply jumping logic
ApplyJumping();
// Calculate actual motion
Vector3 movement = moveDirection * moveSpeed + new Vector3(0, verticalSpeed, 0) + inAirVelocity;
movement *= Time.deltaTime;
// Move the controller
CharacterController controller = GetComponent<CharacterController>();
collisionFlags = controller.Move(movement);
// ANIMATION sector
if (_animation)
{
if (_characterState == CharacterState.Jumping)
{
if (!jumpingReachedApex)
{
_animation[jumpPoseAnimation.name].speed = jumpAnimationSpeed;
_animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever;
_animation.CrossFade(jumpPoseAnimation.name);
}
else
{
_animation[jumpPoseAnimation.name].speed = -landAnimationSpeed;
_animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever;
_animation.CrossFade(jumpPoseAnimation.name);
}
}
else
{
if (controller.velocity.sqrMagnitude < 0.1f)
{
_animation.CrossFade(idleAnimation.name);
}
else
{
if (_characterState == CharacterState.Running)
{
_animation[runAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, runMaxAnimationSpeed);
_animation.CrossFade(runAnimation.name);
}
else if (_characterState == CharacterState.Trotting)
{
_animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, trotMaxAnimationSpeed);
_animation.CrossFade(walkAnimation.name);
}
else if (_characterState == CharacterState.Walking)
{
_animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, walkMaxAnimationSpeed);
_animation.CrossFade(walkAnimation.name);
}
}
}
}
// ANIMATION sector
// Set rotation to the move direction
if (IsGrounded())
{
transform.rotation = Quaternion.LookRotation(moveDirection);
}
else
{
Vector3 xzMove = movement;
xzMove.y = 0;
if (xzMove.sqrMagnitude > 0.001f)
{
transform.rotation = Quaternion.LookRotation(xzMove);
}
}
// We are in jump mode but just became grounded
if (IsGrounded())
{
lastGroundedTime = Time.time;
inAirVelocity = Vector3.zero;
if (jumping)
{
jumping = false;
SendMessage("DidLand", SendMessageOptions.DontRequireReceiver);
}
}
}
void OnControllerColliderHit(ControllerColliderHit hit)
{
// Debug.DrawRay(hit.point, hit.normal);
if (hit.moveDirection.y > 0.01f)
return;
}
float GetSpeed()
{
return moveSpeed;
}
public bool IsJumping()
{
return jumping;
}
bool IsGrounded()
{
return (collisionFlags & CollisionFlags.CollidedBelow) != 0;
}
Vector3 GetDirection()
{
return moveDirection;
}
public bool IsMovingBackwards()
{
return movingBack;
}
public float GetLockCameraTimer()
{
return lockCameraTimer;
}
bool IsMoving()
{
return Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal")) > 0.5f;
}
bool HasJumpReachedApex()
{
return jumpingReachedApex;
}
bool IsGroundedWithTimeout()
{
return lastGroundedTime + groundedTimeout > Time.time;
}
void Reset()
{
gameObject.tag = "Player";
}
}
There are two lines under Update() that handle rotation:
transform.rotation = Quaternion.LookRotation(moveDirection);
and
transform.rotation = Quaternion.LookRotation(xzMove);
Follow the variables moveDirection and xzMove to see how the values are actually determined. It should be pretty straight forward. Hint: moveDirection located in the function UpdateSmoothedMovementDirection(). moveDirection is also used to calculate xzMove using movement. The rest I leave up to you.
Edit: The section of code that actually processes movement is inside UpdateSmoothedMovementDirection(). Look down to if (grounded) --> if (targetDirection != Vector3.zero). It is this area that processes movement. It is the if (targetDirection < walkSpeed * 0.9f && grounded) where movement snaps at 90 degrees. This is the intended function.
I swapped that code out with the code in the else statement, and at slow speeds the avatar moved more naturally. The avatar will only walk at 45 degrees when either both horizontal and vertical are toggled simultaneously. In other words, pressing up + left, or down + right, etc.
If you don't want the snap behavior, just use the code in the else statement and delete the conditional statements. Then your avatar will always turn smoothly.
I have a ThirdPersonController in the Hierarchy.
Then i'm adding to it a Nav Mesh Agent.
The dragging to it the scrip in c#.
Then in the Inspector i'm adding in the script part the agent.
Then baking.
And it was working more or less with some stuttering but was working.
The character ThirdPersonController walked automatic to specific point in this case to a cylinder i have on my Terrain.
I can't figure out why first time/s it's working fine but then now i have this error.
This is the script i'm using for the automatic walk:
using System.Collections;
using UnityStandardAssets.Characters.ThirdPerson;
public class BasicAi : MonoBehaviour {
public NavMeshAgent agent;
public ThirdPersonCharacter character;
public enum State {
PATROL,
CHASE
}
public State state;
private bool alive;
// Variables for patrolling
public GameObject[] waypoints;
private int waypointInd = 0;
public float patrolSpeed = 0.5f;
// Variable for chasing
public float chaseSpeed = 1f;
public GameObject target;
// Use this for initialization
void Start () {
agent = GetComponent<NavMeshAgent> ();
character = GetComponent<ThirdPersonCharacter>();
agent.updatePosition = true;
agent.updateRotation = false;
state = BasicAi.State.PATROL;
alive = true;
StartCoroutine ("FSM");
}
IEnumerator FSM()
{
while (alive)
{
switch (state)
{
case State.PATROL:
Patrol ();
break;
case State.CHASE:
Chase ();
break;
}
yield return null;
}
}
void Patrol()
{
agent.speed = patrolSpeed;
if (Vector3.Distance (this.transform.position, waypoints [waypointInd].transform.position) >= 2) {
agent.SetDestination (waypoints [waypointInd].transform.position);
character.Move (agent.desiredVelocity, false, false);
} else if (Vector3.Distance (this.transform.position, waypoints [waypointInd].transform.position) <= 2) {
waypointInd += 1;
if (waypointInd > waypoints.Length) {
waypointInd = 0;
}
}
else
{
character.Move (Vector3.zero, false, false);
}
}
void Chase()
{
agent.speed = chaseSpeed;
agent.SetDestination (target.transform.position);
character.Move (agent.desiredVelocity, false, false);
}
void OnTriggerEnter(Collider coll)
{
if (coll.tag == "Player")
{
state = BasicAi.State.CHASE;
target = coll.gameObject;
}
}
// Update is called once per frame
void Update () {
}
And the exception error message is:
NullReferenceException: Object reference not set to an instance of an object
UnityStandardAssets.Characters.ThirdPerson.ThirdPersonCharacter.CheckGroundStatus () (at Assets/Standard Assets/Characters/ThirdPersonCharacter/Scripts/ThirdPersonCharacter.cs:215)
UnityStandardAssets.Characters.ThirdPerson.ThirdPersonCharacter.Move (Vector3 move, Boolean crouch, Boolean jump) (at Assets/Standard Assets/Characters/ThirdPersonCharacter/Scripts/ThirdPersonCharacter.cs:54)
BasicAi.Patrol () (at Assets/My Scripts/BasicAi.cs:72)
BasicAi+<FSM>c__Iterator0.MoveNext () (at Assets/My Scripts/BasicAi.cs:55)
UnityEngine.MonoBehaviour:StartCoroutine(String)
BasicAi:Start() (at Assets/My Scripts/BasicAi.cs:43)
When i click on the error message in the Console window it's going to the ThirdPersonCharacter script. The script is from in Unity.
The error is on the line:
m_Animator.applyRootMotion = true;
And this is the ThirdPersonCharacter script where the error is:
using UnityEngine;
namespace UnityStandardAssets.Characters.ThirdPerson
{
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(CapsuleCollider))]
[RequireComponent(typeof(Animator))]
public class ThirdPersonCharacter : MonoBehaviour
{
[SerializeField] float m_MovingTurnSpeed = 360;
[SerializeField] float m_StationaryTurnSpeed = 180;
[SerializeField] float m_JumpPower = 12f;
[Range(1f, 4f)][SerializeField] float m_GravityMultiplier = 2f;
[SerializeField] float m_RunCycleLegOffset = 0.2f; //specific to the character in sample assets, will need to be modified to work with others
[SerializeField] float m_MoveSpeedMultiplier = 1f;
[SerializeField] float m_AnimSpeedMultiplier = 1f;
[SerializeField] float m_GroundCheckDistance = 0.1f;
Rigidbody m_Rigidbody;
Animator m_Animator;
bool m_IsGrounded;
float m_OrigGroundCheckDistance;
const float k_Half = 0.5f;
float m_TurnAmount;
float m_ForwardAmount;
Vector3 m_GroundNormal;
float m_CapsuleHeight;
Vector3 m_CapsuleCenter;
CapsuleCollider m_Capsule;
bool m_Crouching;
void Start()
{
m_Animator = GetComponent<Animator>();
m_Rigidbody = GetComponent<Rigidbody>();
m_Capsule = GetComponent<CapsuleCollider>();
m_CapsuleHeight = m_Capsule.height;
m_CapsuleCenter = m_Capsule.center;
m_Rigidbody.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezeRotationZ;
m_OrigGroundCheckDistance = m_GroundCheckDistance;
}
public void Move(Vector3 move, bool crouch, bool jump)
{
// convert the world relative moveInput vector into a local-relative
// turn amount and forward amount required to head in the desired
// direction.
if (move.magnitude > 1f) move.Normalize();
move = transform.InverseTransformDirection(move);
CheckGroundStatus();
move = Vector3.ProjectOnPlane(move, m_GroundNormal);
m_TurnAmount = Mathf.Atan2(move.x, move.z);
m_ForwardAmount = move.z;
ApplyExtraTurnRotation();
// control and velocity handling is different when grounded and airborne:
if (m_IsGrounded)
{
HandleGroundedMovement(crouch, jump);
}
else
{
HandleAirborneMovement();
}
ScaleCapsuleForCrouching(crouch);
PreventStandingInLowHeadroom();
// send input and other state parameters to the animator
UpdateAnimator(move);
}
void ScaleCapsuleForCrouching(bool crouch)
{
if (m_IsGrounded && crouch)
{
if (m_Crouching) return;
m_Capsule.height = m_Capsule.height / 2f;
m_Capsule.center = m_Capsule.center / 2f;
m_Crouching = true;
}
else
{
Ray crouchRay = new Ray(m_Rigidbody.position + Vector3.up * m_Capsule.radius * k_Half, Vector3.up);
float crouchRayLength = m_CapsuleHeight - m_Capsule.radius * k_Half;
if (Physics.SphereCast(crouchRay, m_Capsule.radius * k_Half, crouchRayLength, Physics.AllLayers, QueryTriggerInteraction.Ignore))
{
m_Crouching = true;
return;
}
m_Capsule.height = m_CapsuleHeight;
m_Capsule.center = m_CapsuleCenter;
m_Crouching = false;
}
}
void PreventStandingInLowHeadroom()
{
// prevent standing up in crouch-only zones
if (!m_Crouching)
{
Ray crouchRay = new Ray(m_Rigidbody.position + Vector3.up * m_Capsule.radius * k_Half, Vector3.up);
float crouchRayLength = m_CapsuleHeight - m_Capsule.radius * k_Half;
if (Physics.SphereCast(crouchRay, m_Capsule.radius * k_Half, crouchRayLength, Physics.AllLayers, QueryTriggerInteraction.Ignore))
{
m_Crouching = true;
}
}
}
void UpdateAnimator(Vector3 move)
{
// update the animator parameters
m_Animator.SetFloat("Forward", m_ForwardAmount, 0.1f, Time.deltaTime);
m_Animator.SetFloat("Turn", m_TurnAmount, 0.1f, Time.deltaTime);
m_Animator.SetBool("Crouch", m_Crouching);
m_Animator.SetBool("OnGround", m_IsGrounded);
if (!m_IsGrounded)
{
m_Animator.SetFloat("Jump", m_Rigidbody.velocity.y);
}
// calculate which leg is behind, so as to leave that leg trailing in the jump animation
// (This code is reliant on the specific run cycle offset in our animations,
// and assumes one leg passes the other at the normalized clip times of 0.0 and 0.5)
float runCycle =
Mathf.Repeat(
m_Animator.GetCurrentAnimatorStateInfo(0).normalizedTime + m_RunCycleLegOffset, 1);
float jumpLeg = (runCycle < k_Half ? 1 : -1) * m_ForwardAmount;
if (m_IsGrounded)
{
m_Animator.SetFloat("JumpLeg", jumpLeg);
}
// the anim speed multiplier allows the overall speed of walking/running to be tweaked in the inspector,
// which affects the movement speed because of the root motion.
if (m_IsGrounded && move.magnitude > 0)
{
m_Animator.speed = m_AnimSpeedMultiplier;
}
else
{
// don't use that while airborne
m_Animator.speed = 1;
}
}
void HandleAirborneMovement()
{
// apply extra gravity from multiplier:
Vector3 extraGravityForce = (Physics.gravity * m_GravityMultiplier) - Physics.gravity;
m_Rigidbody.AddForce(extraGravityForce);
m_GroundCheckDistance = m_Rigidbody.velocity.y < 0 ? m_OrigGroundCheckDistance : 0.01f;
}
void HandleGroundedMovement(bool crouch, bool jump)
{
// check whether conditions are right to allow a jump:
if (jump && !crouch && m_Animator.GetCurrentAnimatorStateInfo(0).IsName("Grounded"))
{
// jump!
m_Rigidbody.velocity = new Vector3(m_Rigidbody.velocity.x, m_JumpPower, m_Rigidbody.velocity.z);
m_IsGrounded = false;
m_Animator.applyRootMotion = false;
m_GroundCheckDistance = 0.1f;
}
}
void ApplyExtraTurnRotation()
{
// help the character turn faster (this is in addition to root rotation in the animation)
float turnSpeed = Mathf.Lerp(m_StationaryTurnSpeed, m_MovingTurnSpeed, m_ForwardAmount);
transform.Rotate(0, m_TurnAmount * turnSpeed * Time.deltaTime, 0);
}
public void OnAnimatorMove()
{
// we implement this function to override the default root motion.
// this allows us to modify the positional speed before it's applied.
if (m_IsGrounded && Time.deltaTime > 0)
{
Vector3 v = (m_Animator.deltaPosition * m_MoveSpeedMultiplier) / Time.deltaTime;
// we preserve the existing y part of the current velocity.
v.y = m_Rigidbody.velocity.y;
m_Rigidbody.velocity = v;
}
}
void CheckGroundStatus()
{
RaycastHit hitInfo;
#if UNITY_EDITOR
// helper to visualise the ground check ray in the scene view
Debug.DrawLine(transform.position + (Vector3.up * 0.1f), transform.position + (Vector3.up * 0.1f) + (Vector3.down * m_GroundCheckDistance));
#endif
// 0.1f is a small offset to start the ray from inside the character
// it is also good to note that the transform position in the sample assets is at the base of the character
if (Physics.Raycast(transform.position + (Vector3.up * 0.1f), Vector3.down, out hitInfo, m_GroundCheckDistance))
{
m_GroundNormal = hitInfo.normal;
m_IsGrounded = true;
m_Animator.applyRootMotion = true;
}
else
{
m_IsGrounded = false;
m_GroundNormal = Vector3.up;
m_Animator.applyRootMotion = false;
}
}
}
}
Here is a video of the problem:
https://pbs.twimg.com/tweet_video/CPmbdpMWIAAUesX.mp4
The issue is whenever the ship flies in the direction of its shield, it seems to stop at regular intervals.
Here's the code for the ship and the shield:
public class MoveOnAxis : MonoBehaviour {
public float speed = 1.0f;
public float defaultDrag = 0.0f;
public float maxDrag = 3.0f;
public float maxAngularDrag = 3.0f;
public float maxTumble = 720;
public Transform shield;
private float distance;
private float hAxis;
private float deadzone = 0.15f;
private float aVel;
private Rigidbody2D rb;
// Use this for initialization
void Start ()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update ()
{
hAxis = Input.GetAxis("Horizontal");
aVel = rb.angularVelocity;
if(Mathf.Abs(hAxis) > 0.15f) //Controlls ship rotation
{
if(aVel > 10.0f) //if spinning out after a crash clockwise
{
if(aVel <= maxTumble && hAxis > deadzone)
{
rb.angularVelocity -= hAxis*speed*2;
}
else if(aVel < maxTumble && hAxis < -deadzone)
{
rb.angularVelocity -= hAxis*speed*2;
}
else if(aVel > maxTumble && hAxis < -deadzone)
{
rb.angularVelocity = maxTumble;
}
}
else if (aVel < -10.0f) //if spinning out of a crash anti-clockwise
{
if(aVel >= -maxTumble && hAxis < -deadzone)
{
rb.angularVelocity -= hAxis*speed*2;
}
else if(aVel > -maxTumble && hAxis > deadzone)
{
rb.angularVelocity -= hAxis*speed*2;
}
else if(aVel < -maxTumble && hAxis > deadzone)
{
rb.angularVelocity = -maxTumble;
}
}
else //if no physics angular momentum go back to using transform for rotation
{
rb.angularVelocity = 0;
transform.Rotate(0.0f, 0.0f, hAxis*-speed);
}
}
if(Input.GetAxis("triggerAxis") > 0.1f) //Controlls ship accelleration and decelleration
{
//distance = Mathf.Abs((transform.position - shield.position).magnitude);
//if (distance <= 1.0f && distance >= 0.6f)
//{
rb.AddForce(transform.up * speed * Input.GetAxis("triggerAxis"));
//}
//else if (distance < 0.6f || distance > 1.0f)
//{
// rb.velocity = new Vector2(0f,0f);
//}
}
if(Input.GetAxis("triggerAxis") < -0.1f)
{
rb.drag = maxDrag*-Input.GetAxis("triggerAxis");
rb.angularDrag = maxAngularDrag*-Input.GetAxis("triggerAxis");
}
else
{
rb.drag = defaultDrag;
rb.angularDrag = defaultDrag;
}
}
}
and
public class ShieldMovement : MonoBehaviour {
public Transform target; //player shield is attaced to
public float circSpeed = 0.1f; // Speed Shield moves around ship
private Vector3 direction = Vector3.up;
private float distance = 0.8f; // distance from player so it doesn't clip
private float deadzone = 0.15f;
private float separation;
private bool canMove = true;
private Rigidbody2D tRB;
private Rigidbody2D rb;
// Use this for initialization
void Start ()
{
tRB = target.GetComponent<Rigidbody2D>();
rb = GetComponent<Rigidbody2D>();
}
void OnCollisionEnter2D (Collision2D other)
{
canMove = false;
}
void OnCollisionStay2d(Collision2D other)
{
canMove = false;
}
void OnCollisionExit2D (Collision2D other)
{
canMove = true;
}
// Update is called once per frame
void Update () {
float rh = Input.GetAxisRaw("rightH");
float rv = Input.GetAxisRaw("rightV");
separation = Mathf.Abs((transform.position - target.position).magnitude);
if(Mathf.Abs(rh) > deadzone || Mathf.Abs(rv) > deadzone)
{
Vector3 targetDir = new Vector3(rh, rv, 0.0f);
direction = Vector3.Slerp(transform.position-target.position, targetDir, circSpeed);
}
Ray ray = new Ray(target.position, direction); // cast ray in direction of point on circle shield is to go
if(canMove)
{
transform.position = ray.GetPoint(distance); //move shield to the ray as far as the distance
}
else if(!canMove)
{
tRB.velocity = new Vector2(0.0f, 0.0f);
//rb.velocity = new Vector2(0.0f, 0.0f);
transform.position = transform.position;
}
if(separation != distance) //If the shield get torn away from the ship
{
transform.position = ray.GetPoint(distance); //move shield to the ray as far as the distance
}
float angleY = transform.position.y - target.position.y;
float angleX = -(transform.position.x - target.position.x);
float angle = Mathf.Atan2 (angleY, angleX) * Mathf.Rad2Deg-90; //Get angle
if(Mathf.Abs(rh) > deadzone || Mathf.Abs(rv) > deadzone)
{
transform.rotation = Quaternion.AngleAxis(angle,Vector3.forward*-1); // keep shield facing outwards in respect to player
}
}
}
I've tried taking out the stuff that stops moving the ship like tRB.velocity = new Vector2(0.0f, 0.0f); but it didn't make any difference at all. Any ideas on what I need to do here?
Edit
Removing the collider from the shield fixes the problem so it seems like somehow the shield is colliding with the ship even though it doesn't look like it and the raycast should keep it far enough away from the ship. Not sure where to go from here.
For physics system updates, it's best practice to put them in FixedUpdate() instead of Update(). The former can be used to change the velocity or add forces, and the latter can be used for getting the input from the user.
To prevent the ship and shield from colliding, use a different tag on each one, then compare the other.collider.tag to ignore those collisions.
// e.g. in ShieldMovement
void OnCollisionEnter2D (Collision2D other)
{
if (other.collider.tag != "Ship") {
canMove = false;
}
}
It seems the shield was colliding with the ship somehow, once I put them on separate non interacting layers the problem went away :D
I'm working on a project where I'm trying to make my character move by jumping at an angle. Right now during the frame updates, the character will pivot back and forth and when the right key is pressed, they will jump. This code causes them to jump at an angle, but they always return to their original position.
Additionally, I have two characters who start on opposite sides of the stage, but when I start the game they teleport to the same position. I've spent a lot of time reviewing my code but I can't seem to get this to work. Any help you can provide?
using UnityEngine;
using System.Collections;
public class Freg : MonoBehaviour {
public GameObject Tounge;
public float gravity;
public float tempScale = 1;
public float MaxJump = 8f;
public float MinJump = 0.1f;
static float yVector = 0;
static float xVector = 0;
static bool grounded = true;
bool isleft = false;
Vector3 farthestleft;
Vector3 farthestright;
// Use this for initialization
void Start () {
farthestleft = new Vector3 (-33.7f, 50.2f, 24.8f);
farthestright = new Vector3 (22.56f, 54.83f, -15.12f);
}
void OnTriggerEnter (Collider other) {
if (other.GetComponent<Collider> ().tag == "Ground") {
grounded = true;
yVector = 0;
//xVector = 0;
Vector3 onGround = new Vector3 (transform.position.x, -4.86f, transform.position.z);
transform.position = onGround;
} else
grounded = false;
}
// Update is called once per frame
void Update () {
/*if (Input.GetKey (KeyCode.UpArrow) == true) {
Tounge.transform.localScale.Set (1, 0.5f, 1);
} else {
Tounge.transform.localScale.Set (1, 1, 1);
}*/
if (grounded == false) {
yVector -= gravity;
}
if (Input.GetKeyDown (KeyCode.UpArrow) == true && grounded == true) {
MinJump += 0.5f;
} else if (MinJump > 0.1f){
yVector += MinJump;
xVector += MinJump;
MinJump = 0.1f;
grounded = false;
}
Vector3 stuff = new Vector3 (transform.localPosition.y + xVector, transform.position.y + yVector, transform.position.z);
transform.position = stuff;
float t = Mathf.PingPong (Time.time * 0.5f * 2.0f, 1.0f);
transform.eulerAngles = Vector3.Lerp (farthestright, farthestleft, t);
}
}
it looks like you should update the current position during the if statements, rather than after that way on each update, the actual position is moving based on the decision rather than just the end of the loop.
I have this problem which I have been trying to figure out for quite some time already. The code I have below is almost complete. I just need to add this additional feature it should work how I want it to work.
So what I want to implement into the code is the make alertedLock false when !withinRange.
But for some reason no matter how i do it. It doesnt work. Because the problem i have is that, when i implement some kind of code to do that, everything goes back to normal.
Thanks in advance.
Edit
The script should be doing this:
If player !withinRange && !withinAngle of enemy then, enemy.color.blue;
If player is not within Range for enemy to detect and player is not within certain Angle for enemy to detect. It means, player is not detected by enemy. So we use Color.Blue to represent that.
If player !withinRange && withinAngle of enemy then, enemy.color.blue;
If player is not within Range for enemy to detect and player is within Angle for enemy to detect. It means, player is still not detect by enemy. So we use Color.Blue to represent that.
If player withinRange && !withinAngle of enemy then, enemy.color.red;
If player is within Range for enemy to detect and player is not within Angle for enemy to detect player. It means, enemy has detected something within Range but doesnt meet all the requirements, that is, withinAngle = true. So in this case we use Color.Red to represent that.
If player withinRange && withinAngle of enemy then, enemy.color.green;
If player is within Range for enemy to detect and player is within Angle for enemy to detect player. It means, player has successfully killed the the enemy. Therefore, using Color.Green to represent that.
If player withinRange && touchRestrictedRaycast of enemy then, enemy.color.magenta (forever) unless !withinRange && !withinAnge
If player is within Range for enemy to detect and player is not within Angle for enemy to detect player. But however then hits the raycast, touchRestrictedRaycast. This will make a lock. So the player cant kill the enemy from a invalid position. So when this happens, the player can no longer kill the enemy. Unless the player is totally out of Range of the enemies detection.
The problem is 5. I dont know how to code 5.
Edit
When i tried to code it outside the forloop , that is,
if (alertedLock && !withinRange) {
alertedLock = false;
}
Does doesnt solve the problem. It returns the solution to where alertedLock is always false
Even when i try to apply it inside the for loop. Such like,
if(withinRange) {
// Inside
if(alertedLock) {
gameObject.renderer.material.color = Color.magenta;
}
if(!alertedLock) {
if(enemyAngleTLUP || enemyAngleTLLEFT) {
alertedLock = true;
}
if(withinAngle) {
gameObject.renderer.material.color = Color.green;
}
if(!withinAngle) {
gameObject.renderer.material.color = Color.red;
}
}
}
if (!withinRange){
if(alteredLock) {
alertedLock = false;
}
}
There is a problem when i do this, its because once it detects the first raycast detection. It ignores the rest, and so it has this color state problem.
I found out this problem on my earlier questions, here:
https://gamedev.stackexchange.com/questions/90329/raycast-flashing-problem
Edit
alertedLock is just a bool which determines when the player has touched the restricted raycast. Due to the fact the player can only kill the enemy from a certain range and angle (withinRange && withinAngle). This is why we have alertedLock.
However, when alertedLock is true. It can only be turned off when the player isnt within the kill range of the enemy (!withinRange)
using UnityEngine;
using System.Collections;
public class Script_v2 : MonoBehaviour {
// Player Properties
private GameObject player;
public Vector3 playerSize;
private Vector3 playerTransform;
public Vector3 playerTransformTL;
public Vector3 playerTransformTR;
public Vector3 playerTransformBL;
public Vector3 playerTransformBR;
private Vector3 newPlayerTransformTL;
private Vector3 newPlayerTransformTR;
private Vector3[] playerRaycastPoints;
// Enemy Properties
private Vector3 enemyTransformTL;
private Vector3 enemyTransformTR;
private Vector3 enemyTransformBL;
private Vector3 enemyTransformBR;
public float distance;
public Vector3 enemySize;
// Detection Alerts
public bool outOfVision;
public bool alerted;
public bool alertedLock;
public bool withinRange;
public bool withinAngle;
public bool dead;
Ray ray;
RaycastHit hit;
// Use this for initialization
void Start () {
playerRaycastPoints = new Vector3[4];
distance = 3f;
player = GameObject.FindGameObjectWithTag ("Player");
}
// Update is called once per frame
void Update () {
enemyTransformTL = new Vector3 (transform.position.x - 0.5f, transform.position.y + 0.5f, transform.position.z);
enemyTransformTR = new Vector3 (transform.position.x + 0.5f, transform.position.y + 0.5f, transform.position.z);
enemyTransform_TL_TR ();
Reference_Player_Transform_Points ();
Player_Transform_Points_Detection ();
Debug.Log (alerted + " " + alertedLock);
}
void OnDrawGizmos() {
Gizmos.color = Color.blue;
Gizmos.DrawWireSphere (new Vector3(transform.position.x - 0.5f, transform.position.y + 0.5f, transform.position.z), distance);
//Gizmos.DrawWireSphere (new Vector3(transform.position.x + 0.5f, transform.position.y + 0.5f, transform.position.z), distance);
}
public void enemyTransform_TL_TR() {
if (alertedLock && !withinRange) {
alertedLock = false;
}
if (!alertedLock) {
gameObject.renderer.material.color = Color.blue;
}
for (int i = 0; i < playerRaycastPoints.Length; i++) {
double enemyAngleTL = Mathf.Atan2(playerRaycastPoints[i].y - ( transform.position.y + 0.5f ),
playerRaycastPoints[i].x - ( transform.position.x - 0.5f )) * 180f / 3.14159265f;
//Debug.Log (enemyAngleTL);
double enemyAngleTR = Mathf.Atan2 (playerRaycastPoints[i].y - (transform.position.y + 0.5f),
playerRaycastPoints[i].x - (transform.position.x + 0.5f)) * 180f / 3.14159265f;
Vector3 directionTL = (playerRaycastPoints[i] - enemyTransformTL).normalized;
Ray rayTL = new Ray(enemyTransformTL, directionTL);
RaycastHit hitTL;
Vector3 directionTR = (playerRaycastPoints[i] - enemyTransformTR).normalized;
Ray rayTR = new Ray (enemyTransformTR, directionTR);
RaycastHit hitTR;
withinRange = Physics.Raycast (rayTL, out hitTL, distance);
withinAngle = enemyAngleTL > 90 && enemyAngleTL < 180;
RaycastHit hitTPUP;
RaycastHit hitTPLEFT;
bool enemyAngleTLUP = Physics.Raycast(enemyTransformTL, Vector3.up, out hitTPUP, distance);
bool enemyAngleTLLEFT = Physics.Raycast(enemyTransformTL, Vector3.left, out hitTPLEFT, distance);
Debug.DrawRay(enemyTransformTL, Vector3.up * distance);
Debug.DrawRay(enemyTransformTL, Vector3.left * distance);
if(withinRange) {
// Inside
if(alertedLock) {
gameObject.renderer.material.color = Color.magenta;
}
if(!alertedLock) {
if(enemyAngleTLUP || enemyAngleTLLEFT) {
alertedLock = true;
}
if(withinAngle) {
gameObject.renderer.material.color = Color.green;
}
if(!withinAngle) {
gameObject.renderer.material.color = Color.red;
}
}
}
}
}
private void Reference_Player_Transform_Points() {
playerSize = player.transform.localScale;
playerTransformTL = new Vector3(player.transform.position.x - (playerSize.x / 2),
player.transform.position.y + playerSize.y / 2,
player.transform.position.z);
playerTransformTR = new Vector3(player.transform.position.x + (playerSize.x / 2),
player.transform.position.y + playerSize.y / 2,
player.transform.position.z);
playerTransformBL = new Vector3(player.transform.position.x - (playerSize.x / 2),
player.transform.position.y - playerSize.y / 2,
player.transform.position.z);
playerTransformBR = new Vector3(player.transform.position.x + (playerSize.x / 2),
player.transform.position.y - playerSize.y / 2,
player.transform.position.z);
playerRaycastPoints [0] = playerTransformTL;
playerRaycastPoints [1] = playerTransformTR;
playerRaycastPoints [2] = playerTransformBL;
playerRaycastPoints [3] = playerTransformBR;
/*
Debug.Log (playerTransformTL);
Debug.Log (playerTransformTR);
Debug.Log (playerTransformBL);
Debug.Log (playerTransformBR);
*/
}
private void Player_Transform_Points_Detection() {
float eTLpTL = Vector3.Distance (enemyTransformTL, playerTransformTL);
float eTLpTR = Vector3.Distance (enemyTransformTL, playerTransformTR);
float eTLpBL = Vector3.Distance (enemyTransformTL, playerTransformBL);
float eTLpBR = Vector3.Distance (enemyTransformTL, playerTransformBR);
float eTRpTL = Vector3.Distance (enemyTransformTR, playerTransformTL);
float eTRpTR = Vector3.Distance (enemyTransformTR, playerTransformTR);
float eTRpBL = Vector3.Distance (enemyTransformTR, playerTransformBL);
float eTRpBR = Vector3.Distance (enemyTransformTR, playerTransformBR);
float eTLMin = Mathf.Min (eTLpTL, eTLpTR, eTLpBL, eTLpBR);
if (eTLMin == eTLpTL) {
newPlayerTransformTL = playerTransformTL;
// Debug.Log("eTLpTL");
}
else if(eTLMin == eTLpTR) {
newPlayerTransformTL = playerTransformTR;
// Debug.Log("eTLpTR");
}
else if(eTLMin == eTLpBL) {
newPlayerTransformTL = playerTransformBL;
// Debug.Log("eTLpBL");
}
else if(eTLMin == eTLpBR) {
newPlayerTransformTL = playerTransformBR;
// Debug.Log("eTLpBR");
}
float eTRMin = Mathf.Min (eTRpTL, eTRpTR, eTRpBL, eTRpBR);
if(eTRMin == eTRpTL) {
newPlayerTransformTR = playerTransformTL;
// Debug.Log("eTRpTL");
}
else if(eTRMin == eTRpTR) {
newPlayerTransformTR = playerTransformTR;
// Debug.Log("eTRpTR");
}
else if(eTRMin == eTRpBL) {
newPlayerTransformTR = playerTransformBL;
// Debug.Log("eTRpBL");
}
else if(eTRMin == eTRpBR) {
newPlayerTransformTR = playerTransformBR;
// Debug.Log("eTRpBR");
}
}
}