Персонаж проходит сквозь статические объекты

Форум для самых маленьких, а так же тех, кому недосуг читать справку самостоятельно.

Персонаж проходит сквозь статические объекты

Сообщение eugine 02 мар 2013, 12:39

Есть стандартный персонаж из примеров construction worker. На нём висит скрипт:
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;

    public class MovePlayer : MonoBehaviour
     {
         public float stopStart = 1.5f, speed = 5f, rotationSpeed = 100f, heightPlayer = 1f;

         private float mag, angleToTarget;
         private Ray ray;
         private RaycastHit hit;
         private Vector3 dir;
         private Vector3 target = new Vector3();
         private Vector3 lastTarget = new Vector3();
       
                 public AnimationClip a_Idle;
                 public float a_IdleSpeed = 1;
                 public AnimationClip a_Walk;
                 public float a_WalkSpeed = 2;

         private bool walk;
       
                 private void Start(){
                        animation[a_Idle.name].speed = a_IdleSpeed;
                        animation[a_Walk.name].speed = a_WalkSpeed;
                        animation.CrossFade(a_Idle.name);
                 }

         private void Update()
         {
             if (Input.GetMouseButton(1))
             {
                 ray = UnityEngine.Camera.mainCamera.ScreenPointToRay(Input.mousePosition);
                 if (Physics.Raycast(ray, out hit, 10000.0f,1<<9))
                 {
                     target = hit.point;
                 }
             }
             LookAtThis();
             MoveTo();
         }

         private void CalculateAngle(Vector3 temp)
         {
             dir = new Vector3(temp.x, transform.position.y, temp.z) - transform.position;
             angleToTarget = Vector3.Angle(dir, transform.forward);
         }

         private void LookAtThis()
         {
                 //if (target != lastTarget)
                 //{
                     CalculateAngle(target);
                     //if(angleToTarget > 3)
                         transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(dir), rotationSpeed * UnityEngine.Time.deltaTime);
                 //}
         }

         private void MoveTo()
         {
             if (target != lastTarget)
             {
                 if ((transform.position - target).sqrMagnitude > heightPlayer + 0.1f)
                 {
                     if (!walk)
                     {
                                                 animation.CrossFade(a_Walk.name);
                         walk = true;
                     }
                     mag = (transform.position - target).magnitude;
                     transform.position = Vector3.MoveTowards(transform.position, target, mag > stopStart ? speed * UnityEngine.Time.deltaTime : Mathf.Lerp(speed * 0.5f, speed, mag / stopStart) * UnityEngine.Time.deltaTime);
                     ray = new Ray(transform.position, -Vector3.up);
                     //if (Physics.Raycast(ray, out hit, 1000.0f))
                     //{
                         transform.position = new Vector3(transform.position.x, hit.point.y + heightPlayer, transform.position.z);
                     //}
                 }
                 else
                 {
                     lastTarget = target;
                     if (walk)
                     {
                                                 animation.CrossFade(a_Idle.name);
                         walk = false;
                     }
                 }
             }
         }
     }

На сцене есть поверхность Plane и Куб. Проблема в том что при щелчке мышкой по поверхности персонаж пройдет куб насквозь как будто его и нет. Но если повесить на персонажа стандартное управление с помощью клавиатуры:
Синтаксис:
Используется javascript
// Require a character controller to be attached to the same game object
@script RequireComponent(CharacterController)

public var idleAnimation : AnimationClip;
public var walkAnimation : AnimationClip;
public var runAnimation : AnimationClip;
public var jumpPoseAnimation : AnimationClip;

public var walkMaxAnimationSpeed : float = 0.75;
public var trotMaxAnimationSpeed : float = 1.0;
public var runMaxAnimationSpeed : float = 1.0;
public var jumpAnimationSpeed : float = 1.15;
public var landAnimationSpeed : float = 1.0;

private var _animation : Animation;

enum CharacterState {
        Idle = 0,
        Walking = 1,
        Trotting = 2,
        Running = 3,
        Jumping = 4,
}

private var _characterState : CharacterState;

// The speed when walking
var walkSpeed = 2.0;
// after trotAfterSeconds of walking we trot with trotSpeed
var trotSpeed = 4.0;
// when pressing "Fire3" button (cmd) we start running
var runSpeed = 6.0;

var inAirControlAcceleration = 3.0;

// How high do we jump when pressing jump and letting go immediately
var jumpHeight = 0.5;

// The gravity for the character
var gravity = 20.0;
// The gravity in controlled descent mode
var speedSmoothing = 10.0;
var rotateSpeed = 500.0;
var trotAfterSeconds = 3.0;

var canJump = true;

private var jumpRepeatTime = 0.05;
private var jumpTimeout = 0.15;
private var groundedTimeout = 0.25;

// The camera doesnt start following the target immediately but waits for a split second to avoid too much waving around.
private var lockCameraTimer = 0.0;

// The current move direction in x-z
private var moveDirection = Vector3.zero;
// The current vertical speed
private var verticalSpeed = 0.0;
// The current x-z move speed
private var moveSpeed = 0.0;

// The last collision flags returned from controller.Move
private var collisionFlags : CollisionFlags;

// Are we jumping? (Initiated with jump button and not grounded yet)
private var jumping = false;
private var jumpingReachedApex = false;

// Are we moving backwards (This locks the camera to not do a 180 degree spin)
private var movingBack = false;
// Is the user pressing any keys?
private var isMoving = false;
// When did the user start walking (Used for going into trot after a while)
private var walkTimeStart = 0.0;
// Last time the jump button was clicked down
private var lastJumpButtonTime = -10.0;
// Last time we performed a jump
private var lastJumpTime = -1.0;


// the height we jumped from (Used to determine for how long to apply extra jump power after jumping.)
private var lastJumpStartHeight = 0.0;


private var inAirVelocity = Vector3.zero;

private var lastGroundedTime = 0.0;


private var isControllable = true;

function 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 var idleAnimation : AnimationClip;
public var walkAnimation : AnimationClip;
public var runAnimation : AnimationClip;
public var jumpPoseAnimation : AnimationClip;  
        */

        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.");
        }
                       
}


function UpdateSmoothedMovementDirection ()
{
        var cameraTransform = Camera.main.transform;
        var grounded = IsGrounded();
       
        // Forward vector relative to the camera along the x-z plane   
        var forward = cameraTransform.TransformDirection(Vector3.forward);
        forward.y = 0;
        forward = forward.normalized;

        // Right vector relative to the camera
        // Always orthogonal to the forward vector
        var right = Vector3(forward.z, 0, -forward.x);

        var v = Input.GetAxisRaw("Vertical");
        var h = Input.GetAxisRaw("Horizontal");

        // Are we moving backwards or looking backwards
        if (v < -0.2)
                movingBack = true;
        else
                movingBack = false;
       
        var wasMoving = isMoving;
        isMoving = Mathf.Abs (h) > 0.1 || Mathf.Abs (v) > 0.1;
               
        // Target direction relative to the camera
        var 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.0;

                // 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.9 && 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
                var 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
                var targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0);
       
                _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.3)
                        walkTimeStart = Time.time;
        }
        // In air controls
        else
        {
                // Lock camera while in air
                if (jumping)
                        lockCameraTimer = 0.0;

                if (isMoving)
                        inAirVelocity += targetDirection.normalized * Time.deltaTime * inAirControlAcceleration;
        }
       

               
}


function 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);
                }
        }
}


function ApplyGravity ()
{
        if (isControllable)     // don't move player at all if not controllable.
        {
                // Apply gravity
                var jumpButton = Input.GetButton("Jump");
               
               
                // When we reach the apex of the jump we send out a message
                if (jumping && !jumpingReachedApex && verticalSpeed <= 0.0)
                {
                        jumpingReachedApex = true;
                        SendMessage("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);
                }
       
                if (IsGrounded ())
                        verticalSpeed = 0.0;
                else
                        verticalSpeed -= gravity * Time.deltaTime;
        }
}

function CalculateJumpVerticalSpeed (targetJumpHeight : float)
{
        // 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);
}

function DidJump ()
{
        jumping = true;
        jumpingReachedApex = false;
        lastJumpTime = Time.time;
        lastJumpStartHeight = transform.position.y;
        lastJumpButtonTime = -10;
       
        _characterState = CharacterState.Jumping;
}

function 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
        var movement = moveDirection * moveSpeed + Vector3 (0, verticalSpeed, 0) + inAirVelocity;
        movement *= Time.deltaTime;
       
        // Move the controller
        var controller : CharacterController = 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.1) {
                                _animation.CrossFade(idleAnimation.name);
                        }
                        else
                        {
                                if(_characterState == CharacterState.Running) {
                                        _animation[runAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, runMaxAnimationSpeed);
                                        _animation.CrossFade(runAnimation.name);       
                                }
                                else if(_characterState == CharacterState.Trotting) {
                                        _animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, trotMaxAnimationSpeed);
                                        _animation.CrossFade(walkAnimation.name);      
                                }
                                else if(_characterState == CharacterState.Walking) {
                                        _animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, walkMaxAnimationSpeed);
                                        _animation.CrossFade(walkAnimation.name);      
                                }
                               
                        }
                }
        }
        // ANIMATION sector
       
        // Set rotation to the move direction
        if (IsGrounded())
        {
               
                transform.rotation = Quaternion.LookRotation(moveDirection);
                       
        }      
        else
        {
                var xzMove = movement;
                xzMove.y = 0;
                if (xzMove.sqrMagnitude > 0.001)
                {
                        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);
                }
        }
}

function OnControllerColliderHit (hit : ControllerColliderHit )
{
//      Debug.DrawRay(hit.point, hit.normal);
        if (hit.moveDirection.y > 0.01)
                return;
}

function GetSpeed () {
        return moveSpeed;
}

function IsJumping () {
        return jumping;
}

function IsGrounded () {
        return (collisionFlags & CollisionFlags.CollidedBelow) != 0;
}

function GetDirection () {
        return moveDirection;
}

function IsMovingBackwards () {
        return movingBack;
}

function GetLockCameraTimer ()
{
        return lockCameraTimer;
}

function IsMoving ()  : boolean
{
        return Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal")) > 0.5;
}

function HasJumpReachedApex ()
{
        return jumpingReachedApex;
}

function IsGroundedWithTimeout ()
{
        return lastGroundedTime + groundedTimeout > Time.time;
}

function Reset ()
{
        gameObject.tag = "Player";
}

То при попытке пройти сквозь куб ничего не получится...Помогите разобратся где проблема в первом скрипте?
eugine
UNец
 
Сообщения: 12
Зарегистрирован: 29 дек 2012, 14:48

Re: Персонаж проходит сквозь статические объекты

Сообщение AndreyMust19 02 мар 2013, 14:20

Скорее всего у вас второй скрипт при добавлении строчкой RequiereComponent автоматически добавляет CharacterController. А первый скрипт ничего не требует, на персонаже нет никакой оболочки, поэтому он и проходит.

Если вам нужны столкновения, то не перемещайте персонажа изменением координат, для этого есть специальные методы - Move для CC и AddForce для Rigidbody.
Нужна помощь? Сами, сами, сами, сами, сами... делаем все сами
AndreyMust19
Адепт
 
Сообщения: 1119
Зарегистрирован: 07 июн 2011, 13:19

Re: Персонаж проходит сквозь статические объекты

Сообщение eugine 02 мар 2013, 14:25

все закрываем тему, двигаю не коллайдер, а трансформ...
eugine
UNец
 
Сообщения: 12
Зарегистрирован: 29 дек 2012, 14:48

Re: Персонаж проходит сквозь статические объекты

Сообщение Syberex 02 мар 2013, 14:26

Первый скрипт в отличие от второго не требует CharacterController-а, но даже если он висит на персонаже, он его не использует.
В общем это минимальный скрипт движения персонажа, ни на что вокруг не обращающий внимания.

Второй скрипт (стандартный) использует CharacterController, анализирует коллизии:
Синтаксис:
Используется javascript

....
function Update() {
       
        ....
        // Move the controller
         var controller : CharacterController = GetComponent(CharacterController);
         collisionFlags = controller.Move(movement);
 

и правильно реагирует на препятствия.
Аватара пользователя
Syberex
Адепт
 
Сообщения: 2292
Зарегистрирован: 14 янв 2011, 20:35
Откуда: Кострома
  • Сайт

Re: Персонаж проходит сквозь статические объекты

Сообщение KBEP 02 мар 2013, 14:34

В первом скрипте движение реализуется перемещением трансформ героя с помощью MoveTowards(), эта функция игнорит коллайдеры, просто перемещает объект из одной точки пространства в другую. Во втором скрипте движение реализовано правильно - с помощью CharacterController.Move(). В общем в первом скрипте надо заменить вызов MoveTowards() на CharacterController.Move() с нужными параметрами.
Аватара пользователя
KBEP
Старожил
 
Сообщения: 598
Зарегистрирован: 24 сен 2012, 23:23
Откуда: Калининград, СПб, Северодвинск


Вернуться в Почемучка

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot], Yandex [Bot] и гости: 23