Objects in unity scene and game view are disappearing when I adjust my view - unity3d

So I'm trying to learn Unity DOTS and I've built out a program that renders a bunch of cubes. But for some reason, in both the game view and the scene view, when I move the camera around, the cubes just at the edge of the screen start to disappear. I don't know if maybe there's some setting that causes non-visible objects to not be rendered or something or maybe it's something to do with them being entities?
This is the code I'm using to spawn the tiles:
private void SpawnTiles()
{
EntityArchetype tileArchetype = entityManager.CreateArchetype(
typeof(Translation),
typeof(Rotation),
typeof(RenderMesh),
typeof(RenderBounds),
typeof(LocalToWorld),
typeof(TileComponent)
);
for (float i = 0f; i < gridX; i++)
{
for (float j = 0f; j < gridY; j++)
{
MakeTile(tileArchetype, new float3(i, 0.0f, j));
}
}
}
private void MakeTile(EntityArchetype tileArchetype, float3 translation)
{
Entity tile = entityManager.CreateEntity(tileArchetype);
entityManager.AddComponentData(tile, new Translation
{
Value = translation
});
entityManager.AddComponentData(tile, new TileComponent
{
x = (int) translation.x,
y = (int) translation.y,
z = (int) translation.z,
isOccupied = false,
isTraversable = false,
index = CalculateIndex((int) translation.x, (int) translation.y, (int) translation.z),
cameFromTileIndex = -1
});
entityManager.AddSharedComponentData(tile, new RenderMesh
{
mesh = tileMesh,
material = tileMaterial
});
}
Screenshot showing clipping

This happen when RenderBounds value is left at default(AABB) as it has 0 size/extent hence making your mesh a mere point for the frustum culling system.

Related

Curve and stretch a sprite to mouse click/touch

I wish to create a game object where you can start dragging it by touching somewhere on the line of its collision and to create these "dynamic shapes" by stretching the sprites and readjusting the sprite look and collision according to the drag point.
Adding an illustration for clearance:
Started playing with Sprite Shape Renderer to create these curved sprite tiles but I need to be able to create dynamic ones using the mouse cursor and adjust all collisions.
I've tried to add an AnchorDragger script to the Sprite Shape Renderer object:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.U2D;
public class AnchorDragger : MonoBehaviour
{
const int INVALLID_INSERTED_POINT_INDEX = -1;
public SpriteShapeController spriteShapeController;
private Spline spline;
private int inseretedPointIndex = INVALLID_INSERTED_POINT_INDEX;
void Start()
{
spline = spriteShapeController.spline;
int pointCount = spline.GetPointCount();
for (var i = 0; i < pointCount; i++)
{
Vector3 currentPointPos = spline.GetPosition(i);
Debug.Log("Point " + i + " position: " + currentPointPos);
}
}
// Update is called once per frame
void Update()
{
if (inseretedPointIndex != INVALLID_INSERTED_POINT_INDEX)
{
spline = spriteShapeController.spline;
spline.SetPosition(inseretedPointIndex, Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 1.0f)));
spriteShapeController.BakeCollider();
}
}
void OnMouseDown()
{
Debug.Log("Mouse Down Position:" + Input.mousePosition);
Vector3 mouseDownPos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 1.0f));
Debug.Log("World Position: " + mouseDownPos);
spline = spriteShapeController.spline;
int pointCount = spline.GetPointCount();
int closestPointIndex = int.MaxValue;
float minDistance = int.MaxValue;
for (var i = 0; i < pointCount; i++)
{
Vector3 currentPointPos = spline.GetPosition(i);
float distance = Vector3.Distance(currentPointPos, mouseDownPos);
if (distance < minDistance)
{
minDistance = distance;
closestPointIndex = i;
}
}
spline.InsertPointAt(closestPointIndex, mouseDownPos);
spline.SetTangentMode(closestPointIndex, ShapeTangentMode.Continuous);
inseretedPointIndex = closestPointIndex;
Debug.Log("Inserted point index: " + inseretedPointIndex);
}
void OnMouseUp()
{
Debug.Log("Mouse Up");
spline = spriteShapeController.spline;
spline.RemovePointAt(inseretedPointIndex);
inseretedPointIndex = INVALLID_INSERTED_POINT_INDEX;
}
}
Basically tried to figure the closest point on the spline where I've clicked and then inserting a new point and setting its position on Update to where the mouse is and delete the point on mouse up.Right now I'm having a problem where the drag position is not correct for some reason.Where I clicked, where the new point position is set:
even when I tried to play with where I click and where I take my mouse to while dragging, not sure why, could use help!
Camera.ScreenToWorldPoint isn't appropriate here because you don't already know how far away to check from the camera, which is needed for the z position. An incorrect z component would give the nearest point on the spline to some point that the mouse is aligned with, but not on the sprite, and would modify the spline at an unexpected position:
Instead, draw a ray from the camera and see where it intersects with the plane the sprite lives on, and use that world position.
In Update:
void Update()
{
if (inseretedPointIndex != INVALLID_INSERTED_POINT_INDEX)
{
spline = spriteShapeController.spline;
Ray r = Camera.main.ScreenPointToRay(Input.mousePosition);
Plane p = new Plane(Vector3.forward,spriteShapeController.spline.GetPosition(0));
float d;
p.Raycast(r,out d);
spline.SetPosition(inseretedPointIndex, r.GetPoint(d));
spriteShapeController.BakeCollider();
}
}
In OnMouseDown:
void OnMouseDown()
{
Debug.Log("Mouse Down Position:" + Input.mousePosition);
Ray r = Camera.main.ScreenPointToRay(Input.mousePosition);
Plane p = new Plane(Vector3.forward, spriteShapeController.spline.GetPosition(0));
float d;
p.Raycast(r,out d);
Vector3 mouseDownPos = r.GetPoint(d);
Debug.Log("World Position: " + mouseDownPos);

Physics2D.OverLapBox detects objects that should be ignored

I'm using a script that looks at the tiles around my GameObject to see if it can detect a collider, through Physics2D.OverlapBox. My problem is that my Player should be ignored by the OverLapBox, as I've set it to look at layers it isn't in, but it is detected everytime.
My Player is in the "Default" layer.
private void SpawnBasicWalls()
{
int layersToScan = LayerMask.GetMask("Floor", "Wall");
//for each tile around this tile
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
Vector2 targetPos = new Vector2(transform.position.x + x, transform.position.y + y);
Collider2D hit = Physics2D.OverlapBox(targetPos, Vector2.one * 0.8f, layersToScan);
//if there isn't a tile around
if (!hit)
{
//Add a wall in that empty adjacent tile.
GameObject goWall = Instantiate(dungMan.wallPrefab, targetPos, Quaternion.identity) as GameObject;
goWall.name = dungMan.wallPrefab.name;
goWall.transform.SetParent(dungMan.transform);
}
else
{
Debug.Log(hit);
}
}
}
//Once it's done, the gameobject is useless and thus is destroyed
Destroy(gameObject);
}
If anyone can tell me what I'm doing wrong, I'd be very grateful.
Physics2D.OverlapBox(targetPos, Vector2.one * 0.8f, layersToScan) is basically calling Physics2D.OverlapBox(point, size, angle) - which means you are sending the layers (casted to int) as an angle.
You need to use one of the overloads that receive a layermask, and make sure you pass it in the right parameter.

Painting sprite in unity

Problem :
I want to make prototype for cleaning windows (I mean cleaning dirty windows) in unity.
I was searching about this subject and finding that I can change pixel by Texture2D.SetPixel().
I try to do it by this method, First I enabled read/write of texture and try this method but nothing happened on my sprite.
So I want to ask it if it's possible to change alpha of the sprite that is clicked by mouse or touched to show the below sprite of original one !?
My Code :
private RaycastHit2D hitInfo;
private SpriteRenderer spriteRendererComponent;
private Color zeroAlpha;
// Use this for initialization
void Start ()
{
spriteRendererComponent = transform.GetComponent<SpriteRenderer>();
zeroAlpha = Color.blue;
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButton(0))
{
MouseClick();
}
}
public void MouseClick()
{
Vector2 mousePosition = Vector2.zero;
mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
hitInfo = Physics2D.Raycast(mousePosition, Vector2.zero);
if (hitInfo)
{
spriteRendererComponent.sprite.texture.SetPixel((int)hitInfo.point.x, (int)hitInfo.point.y, zeroAlpha);
spriteRendererComponent.sprite.texture.Apply();
}
}
Answer :
You can use this thread for Optimizing of changing pixels of sprite
I've found answer about changing pixels of sprite (Painting)
public float radius;
public Color InitialColor;
private RaycastHit2D hitInfo;
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
if (CustomInput.ControlStay())
{
hitInfo = CustomInput.ClickednTouched().hitInfo;
if (hitInfo)
{
UpdateTexture();
}
}
}
public Texture2D CopyTexture2D(Texture2D copiedTexture2D)
{
float differenceX;
float differenceY;
//Create a new Texture2D, which will be the copy
Texture2D texture = new Texture2D(copiedTexture2D.width, copiedTexture2D.height);
//Choose your filtermode and wrapmode
texture.filterMode = FilterMode.Bilinear;
texture.wrapMode = TextureWrapMode.Clamp;
//Center of hit point circle
int m1 = (int)((hitInfo.point.x + 2.5f) / 5 * copiedTexture2D.width);
int m2 = (int)((hitInfo.point.y + 2.5f) / 5 * copiedTexture2D.height);
for (int x = 0; x < texture.width; x++)
{
for (int y = 0; y < texture.height; y++)
{
differenceX = x - m1;
differenceY = y - m2;
//INSERT YOUR LOGIC HERE
if (differenceX * differenceX + differenceY * differenceY <= radius * radius)
{
//This line of code and if statement, turn all texture pixels within radius to zero alpha
texture.SetPixel(x, y, InitialColor);
}
else
{
//This line of code is REQUIRED. Do NOT delete it. This is what copies the image as it was, without any change
texture.SetPixel(x, y, copiedTexture2D.GetPixel(x, y));
}
}
}
//This finalizes it. If you want to edit it still, do it before you finish with Apply(). Do NOT expect to edit the image after you have applied.
texture.Apply();
return texture;
}
public void UpdateTexture()
{
SpriteRenderer mySpriteRenderer = gameObject.GetComponent<SpriteRenderer>();
Texture2D newTexture2D = CopyTexture2D(mySpriteRenderer.sprite.texture);
//Get the name of the old sprite
string tempName = mySpriteRenderer.sprite.name;
//Create a new sprite
mySpriteRenderer.sprite = Sprite.Create(newTexture2D, mySpriteRenderer.sprite.rect, new Vector2(0.5f, 0.5f));
//Name the sprite, the old name
mySpriteRenderer.sprite.name = tempName;
//Update the material
//If you have multiple sprites, you will want to do this in a loop
//mySpriteRenderer.material.mainTexture = newTexture2D;
//mySpriteRenderer.material.shader = Shader.Find("Unlit/Transparent");
}
Another problem :
Finding pixel on sprite :
In Unity3d we have RaycastHit.textureCoord but it doesn't exist anymore in 2D. I was searching about this problem, a lot but I didn't find anything useful.
So I want to know the solution for this problem and I'm wondering why method like textureCoord in 3D doesn't exist in 2D.
Answer :
I've found answer again as you see in the previous code for finding pixel on sprite.
Thread : Finding pixel on sprite in Unity
Check this out!
I have fixed your script. Works on different texture sizes. Different texture places and camera size. Require box collider 2d.
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
public float radius;
public Color InitialColor;
private RaycastHit2D hitInfo;
// Update is called once per frame
void Update()
{
if (Input.GetMouseButton(0))
{
hitInfo = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if (hitInfo)
{
UpdateTexture();
}
}
if (Input.GetMouseButtonUp(0))
{
Resources.UnloadUnusedAssets();
}
}
public Texture2D CopyTexture2D(Texture2D copiedTexture2D)
{
float differenceX;
float differenceY;
//Create a new Texture2D, which will be the copy
Texture2D texture = new Texture2D(copiedTexture2D.width, copiedTexture2D.height);
//Choose your filtermode and wrapmode
texture.filterMode = FilterMode.Bilinear;
texture.wrapMode = TextureWrapMode.Clamp;
//Center of hit point circle
int m1 = (int)((hitInfo.point.x - hitInfo.collider.bounds.min.x) * (copiedTexture2D.width / hitInfo.collider.bounds.size.x));
int m2 = (int)((hitInfo.point.y - hitInfo.collider.bounds.min.y) * (copiedTexture2D.height / hitInfo.collider.bounds.size.y));
//Vector2 extremeScreenPoint = Camera.main.ScreenToWorldPoint(new Vector2(0, 0));
//Debug.Log("extremeScreenPoint= " + extremeScreenPoint.x
// + " hitInfo.point.x =" + hitInfo.point.x
// //+ " mousePosition =" + Camera.main.ScreenToWorldPoint(Input.mousePosition).x
// + " bounds.min =" + hitInfo.collider.bounds.min .x
// + " bounds.max =" + hitInfo.collider.bounds.max .x
// + " size =" + hitInfo.collider.bounds.size.x
// + " hit =" + (hitInfo.point.x - hitInfo.collider.bounds.min.x)
// + " pixels =" + (hitInfo.point.x - hitInfo.collider.bounds.min.x) * (copiedTexture2D.width / hitInfo.collider.bounds.size.x)
// );
for (int x = 0; x < texture.width; x++)
{
for (int y = 0; y < texture.height; y++)
{
differenceX = x - m1;
differenceY = y - m2;
//INSERT YOUR LOGIC HERE
if (differenceX * differenceX + differenceY * differenceY <= radius * radius)
{
//This line of code and if statement, turn all texture pixels within radius to zero alpha
texture.SetPixel(x, y, InitialColor);
}
else
{
//This line of code is REQUIRED. Do NOT delete it. This is what copies the image as it was, without any change
texture.SetPixel(x, y, copiedTexture2D.GetPixel(x, y));
}
}
}
//This finalizes it. If you want to edit it still, do it before you finish with Apply(). Do NOT expect to edit the image after you have applied.
texture.Apply();
//DestroyImmediate(copiedTexture2D, true);
return texture;
}
public void UpdateTexture()
{
SpriteRenderer mySpriteRenderer = gameObject.GetComponent<SpriteRenderer>();
Texture2D newTexture2D = CopyTexture2D(mySpriteRenderer.sprite.texture);
//Get the name of the old sprite
string tempName = mySpriteRenderer.sprite.name;
//Create a new sprite
mySpriteRenderer.sprite = Sprite.Create(newTexture2D, mySpriteRenderer.sprite.rect, new Vector2(0.5f, 0.5f));
//Name the sprite, the old name
mySpriteRenderer.sprite.name = tempName;
//Update the material
//If you have multiple sprites, you will want to do this in a loop
//mySpriteRenderer.material.mainTexture = newTexture2D;
//mySpriteRenderer.material.shader = Shader.Find("Unlit/Transparent");
}
}
I worked with Writing and Reading a Texture once (for a scratching card).
You have to consider that when you change the Pixels of the Sprite, you are changing the pixels for the entire texture. So let's say that i change the pixel 1x1, most likely it will not change the pixel 1x1 in my sprite if i have a bunch of sprites in the same texture. So you have to consider the offsets of the sprite and reposition the pixel that you want to change.
Try to do something like this:
public void MouseClick()
{
Vector2 offset = new Vector2(XXX, YYY);
Vector2 mousePosition = Vector2.zero;
mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
hitInfo = Physics2D.Raycast(mousePosition, Vector2.zero);
if (hitInfo)
{
spriteRendererComponent.sprite.texture.SetPixel((int)hitInfo.point.x + offset.x, (int)hitInfo.point.y + offset.y, zeroAlpha);
spriteRendererComponent.sprite.texture.Apply();
}
}

Wrong result when using setPixel()

I'm dealing with a problem for a few days now with setPixel() on Texture2D.
What i'm doing is getting mouse position or touch position(on android), then using that in setPixel() with transparent color. But the result i'm getting occur elsewhere instead of exactly where the mouse is...
public class EarshPic : MonoBehaviour {
public SpriteRenderer sr;
public SpriteRenderer srO;
public Camera c;
// Use this for initialization
void Start () {
CreateCover();//This method is working fine
}
private void CreateCover()
{
Color color = new Color(0.5F, 0.5f, 0.5F, 1.0F);
int x = srO.sprite.texture.width;
int y = srO.sprite.texture.height;
Texture2D tmpTexture = new Texture2D(srO.sprite.texture.width,
srO.sprite.texture.height);
for (int i = 0; i < tmpTexture.width; i++)
{
for (int j = 0; j < tmpTexture.height; j++)
{
tmpTexture.SetPixel(i, j, color);
}
}
tmpTexture.Apply(true);
sr.sprite = Sprite.Create(tmpTexture, srO.sprite.rect,
new Vector2(0.5f, 0.5f),srO.sprite.pixelsPerUnit);
}
// I have problem in that method
// Vector2 v = mousePostion or touchpostion
void Eraser(Vector2 v)
{
Color color = new Color(0.5F, 0.5f, 0.5F, 0.0F);
sr.sprite.texture.SetPixel(v.x, v.y, color);
sr.sprite.texture.Apply(true);
}
// Update is called once per frame
void Update () {
if(Input.mousePosition!=null)
{
Eraser(Input.mousePosition);
}
if (Input.touchCount == 1)
{
Touch touch = Input.GetTouch(0);
switch (touch.phase)
{
case TouchPhase.Moved:
Eraser(touch.position);
break;
}
}
}
}
Problem
You are mixing different coordinates. This is the case if the texture is not perfectly screen sized. Your click is in screen coordinates and you are using it to set the transparency in texture coordinates.
Solution
This one requires the use of 3D models with colliders and textures on them. For 2D scenario you can use a box and set its texture to your 2D sprite. I don't know any easier method, but hopefully there is.
You have to first convert the screen position to world coordinate ray. This can be done with Camera.ScreenPointToRay.
Then you need to Physics.Raycast that ray to chech which position of the 3d model's collider it is intersecting with.
The intersection point can be changed to texture coordinates with RaycastHit.textureCoord. In the previous link, you can find a complete code example of the whole process.

Unity3D Third Person Controller and Animations

My problem is that a custom walk animation I have set in the third person controller of Unity3D is not shown.
The animation is imported from a FBX file with the model#walk.fbx structure. I know the animation works, because if I use it as the idle animation it shows. On the other hand, it also doesn't seem to be an issue with the controller script, as it works fine with the prototype character.
It seems that the animation being played is the one selected in the Animation component (which has 'Play Automatically' selected). Any attempts to change the animation from the third person controller work for the prototype character, but not for mine.
I don't have nor want run and jump animations. With the prototype character I set the walk animation on each of those with no adverse effects. The controller doesn't turn off animation this way, seeing that there are no log entries in the console from the third person controller script. The relevant line with the CrossFade call is getting called.
Any clues as to where I could look next? Is it more likely an issue with the controller, or with the animation? Something else completely?
Update: Below is the code of my controller. It works fine when I use the sample model of the construction worker that is provided with Unity. The lines with _animation.CrossFade are getting called at the expected times. Using Play or Blend instead doesn't help. There are no errors logged in the console.
For our custom animations however it doesn't work. I am now suspecting the issues lies with the model. Unfortunately I am not at liberty to share a sample of that model. I've asked the animator for further details on how he created the FBX export. Are there any specific settings he needs to use for the model to work in Unity? It remains odd though that the animations do work if I add them indepently to the scene.
// 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 walkMaxAnimationSpeed : float = 0.75;
private var _animation : Animation;
enum CharacterState {
Idle = 0,
Walking = 1,
}
private var _characterState : CharacterState;
// The speed when walking
var walkSpeed = 2.0;
var speedSmoothing = 10.0;
var rotateSpeed = 500.0;
var targetPrecision = 5;
var targetMaxDistance = 200;
// 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 x-z move speed
private var moveSpeed = 0.0;
// The last collision flags returned from controller.Move
private var collisionFlags : CollisionFlags;
// 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;
private var isControllable = true;
private var isTargetting : boolean = false;
private var targetPoint : Vector3 = Vector3.zero;
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.");
if(!idleAnimation) {
_animation = null;
Debug.Log("No idle animation found. Turning off animations.");
}
//_animation[idleAnimation.name] = idleAnimation;
if(!walkAnimation) {
_animation = null;
Debug.Log("No walk animation found. Turning off animations.");
}
//_animation[walkAnimation.name] = walkAnimation;
}
function UpdateSmoothedMovementDirection () {
var cameraTransform = Camera.main.transform;
// 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;
// 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) {
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
targetSpeed *= walkSpeed;
_characterState = CharacterState.Walking;
moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);
}
function UpdateTargettedMovementDirection () {
var cameraTransform = Camera.main.transform;
var wasMoving = isMoving;
isMoving = true;//Mathf.Abs (h) > 0.1 || Mathf.Abs (v) > 0.1;
// Target direction relative to the camera
// var targetDirection = h * right + v * forward;
var targetDirection = Vector3.zero;
targetDirection.x = targetPoint.x - transform.position.x;
targetDirection.z = targetPoint.z - transform.position.z;
targetDirection = targetDirection.normalized;
//Debug.Log("Target direction is " + targetDirection);
// 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) {
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
targetSpeed *= walkSpeed;
_characterState = CharacterState.Walking;
moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);
}
function Update() {
if (!isControllable) {
// kill all inputs if not controllable.
Input.ResetInputAxes();
}
var distance : float = 0;
if (Input.GetMouseButtonUp(0)) {
if (isTargetting) {
isTargetting = false;
// Debug.Log("Stopped moving");
FaceCamera();
} else {
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
var layerMask = 1 << 8; // Terrain is layer 8
var hit : RaycastHit;
Physics.Raycast(Camera.main.transform.position, ray.direction, hit, 1000, layerMask);
distance = Vector3.Distance(transform.position, hit.point);
if (distance <= targetMaxDistance && hit.point != Vector3.zero) {
targetPoint = hit.point;
isTargetting = true;
// Debug.Log("Mouse up at hit " + hit.point + " at distance " + distance);
} else {
isTargetting = false;
// Debug.Log("Ignored mouse up at hit " + hit.point + " at distance " + distance);
}
}
}
if (isTargetting) {
// Debug.Log("Moving to " + targetPoint);
distance = Vector3.Distance(transform.position, targetPoint);
if (distance < targetPrecision) {
// Debug.Log("Reached point " + targetPoint + " at distance " + distance);
isTargetting = false;
FaceCamera();
} else {
UpdateTargettedMovementDirection();
}
} else {
UpdateSmoothedMovementDirection();
}
// Calculate actual motion
var movement = moveDirection * moveSpeed;
movement *= Time.deltaTime;
// Move the controller
var controller : CharacterController = GetComponent(CharacterController);
collisionFlags = controller.Move(movement);
// ANIMATION sector
if (_animation) {
if (controller.velocity.sqrMagnitude < 0.1) {
_animation.CrossFade(idleAnimation.name);
} else {
//_animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0, walkMaxAnimationSpeed);
_animation.CrossFade(walkAnimation.name);
}
} else {
Debug.Log("Animation is null!");
}
// ANIMATION sector
// Set rotation to the move direction
transform.rotation = Quaternion.LookRotation(moveDirection);
}
function OnControllerColliderHit (hit : ControllerColliderHit ) {
// Debug.DrawRay(hit.point, hit.normal);
if (hit.moveDirection.y > 0.01)
return;
}
function GetSpeed () {
return moveSpeed;
}
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 Reset () {
gameObject.tag = "Player";
}
function FaceCamera() {
var cameraTransform = Camera.main.transform;
// Forward vector relative to the camera along the x-z plane
var forward = cameraTransform.TransformDirection(Vector3.forward);
forward.y = 0;
forward = forward.normalized;
moveDirection = -forward;
}
Update 2: The settings used to create the animations are in these screenshots. Are they correct?
Not (yet :-) an answer but I need more space and images.
Since 3.5 Unity3d the way to handle imports based on animation#model.fbx notation has changed and some people reported trouble (s. for example BIG Unity 3.5.0f1 problem with Skinned Rig - Major FAIL). The problem arises when a 2nd root bone comes to play but I could solve this by dragging the animations to the model file prefab (most of my animations are contained in the model and the remaining 2 are no big pain).
Just to be really sure that I understood your answer in the comments section right, you have something like this:
That means:
Within the character model the animations array contains all animations
The number of bones and all names are exactly like in your prototype character
If you open an animation view, you can see a read-only list of all animations of the character selected in hierarchy view
Assuming this is fine some more suggestions:
I can't see any place in the code where you set WrapMode.Loop or animation speed. Are you sure it is configured as Loop in inspector and is not overwritten somewhere.
CrossFade with no parameters assumes 0.3 seconds
What happens after the cross fade call? Does the DefaulTake stops playing?
Can you drag the Walk animation as default
Do you use different animation layers?
What output do you get when you set up Debug.Log ("Walk: " + player.animation.IsPlaying ("Walk"));
[Update]
Let's look at the import settings. Do you have Split Animations
checked and are there maybe wrong values entered at Start and
End like 1-1?
Regarding Toggling of IsPlaying: Please create more output about the AnimationState properties. Most notable speed, length, enabled, weight, ... I have a suspicion that the animation is too short or played too fast.
A walk animation that is no bone animation sounds a bit strange. On the other hand console would cry out loud if bone names are not matching. So I assume there is no problem now.
That is strange, can you post the source&demo?
You can try to check:
Check if the animation names and properties are set correctly in the editor.
Create an object without the controller and make sure the animations were imported correctly.