Пример #1
0
 /// <summary>
 /// Handle ComponentCreated events.
 /// </summary>
 /// <param name="evt">
 /// The <see cref="IEvent"/> event to handle.
 /// </param>
 private void OnComponentCreated(IEvent evt)
 {
     if (evt.EventData is MovableComponent)
     {
         MovableComponent movable = (MovableComponent)evt.EventData;
         movable.Rigidbody       = movable.gameObject.GetComponent <Rigidbody>();
         movable.DesiredPosition = movable.gameObject.transform.position;
     }
 }
Пример #2
0
        /// <summary>
        /// Move the entity, that has the given movable to the desired position.
        /// </summary>
        /// <param name="movable">
        /// The <see cref="MovableComponent"/> movable component of the entity to move.
        /// </param>
        /// <param name="position">
        /// The <see cref="Vector3"/> position to move the entity to.
        /// </param>
        private void MoveMovableToPosition(MovableComponent movable, Vector3 target)
        {
            if (movable == null)
            {
                // This checks, whether the component is still considered alive by Unity.
                // The check is very important, as we are accessing components from Unity
                // now, instead of just C# context components. If the object is Unity-dead,
                // don't do anything here.
                return;
            }

            Transform  transform       = movable.gameObject.transform;
            Vector3    movementVector  = target - transform.position;
            Collider   collider        = movable.gameObject.collider;
            Vector3    colliderExtents = collider.bounds.extents;
            float      movableRange    = Mathf.Max(Mathf.Max(colliderExtents.x, colliderExtents.y), colliderExtents.z) * 2.0f;
            RaycastHit hit;

            // Test to see, if there are any colliders in the movement direction and stop close to the hit point.
            // This is done for all movables here to illustrate the shared use of characteristics (Components) by
            // entities of different types (the Ball and the paddle in this case). The implementation is a hacky,
            // imperformant and buggy though and it should not be used for any real game. In those cases, you may
            // want to use different movement strategies for the paddle and the ball, as their requirements differ.
            if (Physics.Raycast(transform.position, movementVector, out hit, movableRange + movementVector.sqrMagnitude, movable.CollisionMask))
            {
                // There is a collider near by, that might be in the way at the hit point.
                Vector3 collisionPoint = hit.point;

                // Calculate a point outside the collider to cast from, using the maximum
                // extent of the collider along an axis times two, as that should definitely
                // be outside the collider.
                Vector3 movableCastPoint = movementVector.normalized;
                movableCastPoint *= movableRange * 2.0f;
                movableCastPoint += transform.position;

                // Check to find a point in the movement direction, that may collide.
                Ray ray = new Ray(movableCastPoint, movementVector * -1);
                if (collider.Raycast(ray, out hit, Mathf.Infinity))
                {
                    // There is a point, that would actually collide. Substract
                    // its position from that of the blocking collider to get the
                    // new center of the movable. Because the collision vector starts
                    // at twice the distance, the actual distance is distance * 0.5, which
                    // in case of using square magnitude checks needs to also be squared.
                    if ((collisionPoint - hit.point).sqrMagnitude < movementVector.sqrMagnitude)
                    {
                        target = collisionPoint - (hit.point - transform.position);
                    }
                }
            }

            // Set the new target position using the entities transform (as opposed to
            // Rigidbody.MovePosition, as it seems to behave a bit weird).
            transform.position = target;
        }
        /// <summary>
        /// Move the entity, that has the given movable to the desired position.
        /// </summary>
        /// <param name="movable">
        /// The <see cref="MovableComponent"/> movable component of the entity to move.
        /// </param>
        /// <param name="position">
        /// The <see cref="Vector3"/> position to move the entity to.
        /// </param>
        private void MoveMovableToPosition(MovableComponent movable, Vector3 target)
        {
            if (movable == null)
            {
                // This checks, whether the component is still considered alive by Unity.
                // The check is very important, as we are accessing components from Unity
                // now, instead of just C# context components. If the object is Unity-dead,
                // don't do anything here.
                return;
            }

            Transform transform = movable.gameObject.transform;
            Vector3 movementVector = target - transform.position;
            Collider collider = movable.gameObject.collider;
            Vector3 colliderExtents = collider.bounds.extents;
            float movableRange = Mathf.Max(Mathf.Max(colliderExtents.x, colliderExtents.y), colliderExtents.z) * 2.0f;
            RaycastHit hit;

            // Test to see, if there are any colliders in the movement direction and stop close to the hit point.
            // This is done for all movables here to illustrate the shared use of characteristics (Components) by
            // entities of different types (the Ball and the paddle in this case). The implementation is a hacky,
            // imperformant and buggy though and it should not be used for any real game. In those cases, you may
            // want to use different movement strategies for the paddle and the ball, as their requirements differ.
            if (Physics.Raycast(transform.position, movementVector, out hit, movableRange + movementVector.sqrMagnitude, movable.CollisionMask))
            {
                // There is a collider near by, that might be in the way at the hit point.
                Vector3 collisionPoint = hit.point;

                // Calculate a point outside the collider to cast from, using the maximum
                // extent of the collider along an axis times two, as that should definitely
                // be outside the collider.
                Vector3 movableCastPoint = movementVector.normalized;
                movableCastPoint *= movableRange * 2.0f;
                movableCastPoint += transform.position;

                // Check to find a point in the movement direction, that may collide.
                Ray ray = new Ray(movableCastPoint, movementVector * -1);
                if (collider.Raycast(ray, out hit, Mathf.Infinity))
                {
                    // There is a point, that would actually collide. Substract
                    // its position from that of the blocking collider to get the
                    // new center of the movable. Because the collision vector starts
                    // at twice the distance, the actual distance is distance * 0.5, which
                    // in case of using square magnitude checks needs to also be squared.
                    if ((collisionPoint - hit.point).sqrMagnitude < movementVector.sqrMagnitude)
                    {
                        target = collisionPoint - (hit.point - transform.position);
                    }
                }
            }

            // Set the new target position using the entities transform (as opposed to
            // Rigidbody.MovePosition, as it seems to behave a bit weird).
            transform.position = target;
        }