Procedural extrude of mesh problems - c#

I'm trying out some procedural mesh extrusion but I've got two problems at the moment. The code that performs the extrusion is a part of a Unity example package, and is available here (MeshExtrusion.cs)
First problem is that the update to the mesh only shows when an additional point is added to the mesh, the GIF below should highlight this.
Second problem is that the mesh is twisting. I'm guessing this is due to the wrong vertices being extruded, but I'm not 100% sure. Here is my code that is implementing the mesh extrusion:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ExtrudeTest : MonoBehaviour {
private Vector3 currentMousePosition;
private float currentMouseDistance;
MeshExtrusion.Edge[] preComputedEdges;
private Mesh srcMesh;
private List<Matrix4x4> extrusionPoints = new List<Matrix4x4>();
private Matrix4x4 currentTransformMatrix;
GameObject lineObject;
LineRenderer drawLine;
private bool invertFaces = false;
// Use this for initialization
void Start () {
srcMesh = GetComponent<MeshFilter>().sharedMesh;
preComputedEdges = MeshExtrusion.BuildManifoldEdges(srcMesh);
extrusionPoints.Add(transform.worldToLocalMatrix * Matrix4x4.TRS(transform.position, Quaternion.identity, Vector3.one));
lineObject = new GameObject("lineRenderer");
drawLine = lineObject.AddComponent<LineRenderer>();
}
//Store the current world mouse position.
public void storeMouseLocation()
{
Ray ray = Camera.main.ScreenPointToRay(UnityEngine.Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, Mathf.Infinity))
{
currentMousePosition = hit.point;
currentMouseDistance = hit.distance;
currentTransformMatrix = hit.transform.localToWorldMatrix;
}
}
private void adjustMesh()
{
Matrix4x4 worldToLocal = transform.worldToLocalMatrix;
Matrix4x4[] finalSections = new Matrix4x4[extrusionPoints.Count];
Quaternion rotation;
Quaternion previousRotation = Quaternion.identity;
Vector3 direction;
for (int i=0; i < extrusionPoints.Count; i++)
{
if (i == 0)
{
direction = extrusionPoints[0].GetColumn(3) - extrusionPoints[1].GetColumn(3);
rotation = Quaternion.LookRotation(direction, Vector3.up);
previousRotation = rotation;
finalSections[i] = worldToLocal * Matrix4x4.TRS(transform.position, rotation, Vector3.one);
}
else if (i != extrusionPoints.Count - 1)
{
direction = extrusionPoints[i].GetColumn(3) - extrusionPoints[i + 1].GetColumn(3);
rotation = Quaternion.LookRotation(direction, Vector3.up);
// When the angle of the rotation compared to the last segment is too high
// smooth the rotation a little bit. Optimally we would smooth the entire sections array.
if (Quaternion.Angle(previousRotation, rotation) > 20)
{
rotation = Quaternion.Slerp(previousRotation, rotation, 0.5f);
}
previousRotation = rotation;
finalSections[i] = worldToLocal * Matrix4x4.TRS(extrusionPoints[i].GetColumn(3), rotation, Vector3.one);
}
else
{
finalSections[i] = finalSections[i - 1];
}
}
extrudeMesh(finalSections);
}
private void extrudeMesh(Matrix4x4[] sections)
{
Debug.Log("Extruding mesh");
MeshExtrusion.ExtrudeMesh(srcMesh, GetComponent<MeshFilter>().mesh, sections, preComputedEdges, invertFaces);
}
// Update is called once per frame
void Update () {
storeMouseLocation();
drawLine.SetPosition(0, extrusionPoints[extrusionPoints.Count-1].GetColumn(3));
drawLine.SetPosition(1, currentMousePosition);
if (Input.GetMouseButtonDown(0))
{
extrusionPoints.Add(transform.worldToLocalMatrix * Matrix4x4.TRS(transform.position + new Vector3(currentMousePosition.x, currentMousePosition.y, currentMousePosition.z),
Quaternion.identity,
Vector3.one));
}
if (extrusionPoints.Count >=2)
{
adjustMesh();
}
}
}
Here is a GIF that shows how it's currently performing:
https://puu.sh/xeS7e/bfc3d71fba.gif
I'm not entirely sure what is causing these problems, so if anyone could offer any advice or input, I'd greatly appreciate it. Thanks

Related

Cannot implicitly convert type 'UnityEngine.GameObject' to 'GameObject'

Hello everyone and thanks in advance for your answers!
I am a beginner in unity, coding my second game after i finshed a couple of tutorials.
Since today, i noticed that suddenly all my "GameObjects" have a "UnityEngine." in front of them.
I have no idea how that happened, and it is also not just in one script, but all of them. Heres an example of it:
UnityEngine.GameObject item = (UnityEngine.GameObject)Instantiate(itemGOList[i], spawnTransform, spawnRotation);
This worked fine before without the "UnityEngine.", but now it only works when its written this way.
Do you know how this could have happened and how to revert it?
This is one of the scripts:
using UnityEngine;
using UnityEngine.EventSystems;
public class Turret : MonoBehaviour
{
private Transform target;
private Enemy targetEnemy;
[Header("General")]
public float range = 10f;
[Header("Use Bullets/missiles (default)")]
public UnityEngine.GameObject bulletPrefab;
public float fireRate = 1f;
private float fireCountdown = 0f;
public AudioClip shootingSound;
private AudioSource audioSource;
[Header("Use Laser (default)")]
public bool useLaser = false;
public int damageOverTime = 20;
public float slowAmount = .5f;
public LineRenderer lineRenderer;
public ParticleSystem impactEffect;
public Light impactLight;
[Header("Unity Setup Fields")]
public string enemyTag = "Enemy";
public Transform partToRotate;
public float turnSpeed = 10f;
public Transform firePoint;
void Start()
{
InvokeRepeating(nameof(UpdateTarget), 0f, 0.3f); // Call the UpdateTarget Method after 0 seconds, then repeat every 0.3 seconds.
audioSource = GetComponent<AudioSource>(); //Puts the AudioSource of this GO (the turret) into the variable audioSource.
}
void UpdateTarget ()
{
UnityEngine.GameObject[] enemies = UnityEngine.GameObject.FindGameObjectsWithTag(enemyTag); // Find all enemies (and store in a list?).
float shortestDistance = Mathf.Infinity; // Create a float for the shortest distance to an enemy.
UnityEngine.GameObject nearestEnemy = null; // Create a variable which stores the nearest enemy as a gameobject.
foreach (UnityEngine.GameObject enemy in enemies) // Loop through the enemies array.
{
float distanceToEnemy = Vector3.Distance(transform.position, enemy.transform.position); //Get the distance to each enemy and stores it.
if (distanceToEnemy < shortestDistance) // If any of the enemies is closer than the original, make this distance the new shortestDistance and the new enemy to the nearestEnemy.
{
shortestDistance = distanceToEnemy;
nearestEnemy = enemy;
}
}
if (nearestEnemy != null && shortestDistance <= range) // Sets the target to the nearestEnemy (only if its in range and not null).
{
target = nearestEnemy.transform;
targetEnemy = nearestEnemy.GetComponent<Enemy>();
}
else
{
target = null;
}
}
void Update()
{
if (target == null) // If there is no target, do nothing.
{
if (useLaser)
{
if (lineRenderer.enabled)
{
lineRenderer.enabled = false;
impactEffect.Stop();
impactLight.enabled = false;
audioSource.Stop();
}
}
return;
}
LockOnTarget();
if (useLaser)
{
Laser();
}
else
{
if (fireCountdown <= 0f)
{
Shoot();
fireCountdown = 1f / fireRate;
}
fireCountdown -= Time.deltaTime;
}
}
void Laser()
{
targetEnemy.TakeDamage(damageOverTime * Time.deltaTime);
targetEnemy.Slow(slowAmount);
if (!lineRenderer.enabled)
{
lineRenderer.enabled = true;
impactEffect.Play();
impactLight.enabled = true;
if (audioSource.isPlaying == false)
{
audioSource.Play();
}
}
lineRenderer.SetPosition(0, firePoint.position);
lineRenderer.SetPosition(1, target.position);
Vector3 dir = firePoint.position - target.position;
impactEffect.transform.position = target.position + dir.normalized * 1f;
impactEffect.transform.rotation = Quaternion.LookRotation(dir);
}
void LockOnTarget()
{
Vector3 dir = target.position - transform.position; // Store the direction from turret to target.
Quaternion lookRotation = Quaternion.LookRotation(dir); // I have no idea how this works...
Vector3 rotation = Quaternion.Lerp(partToRotate.rotation, lookRotation, Time.deltaTime * turnSpeed).eulerAngles; // Convert quaternion angles to euler angles and Lerp it (smoothing out the transition).
partToRotate.rotation = Quaternion.Euler(0f, rotation.y, 0f); // Only rotate around the y-axis.
}
void Shoot()
{
UnityEngine.GameObject bulletGO = (UnityEngine.GameObject)Instantiate(bulletPrefab, firePoint.position, firePoint.rotation); // Spawn a bullet at the location and rotation of firePoint. (Also makes this a GO to reference it.
Bullet bullet = bulletGO.GetComponent<Bullet>(); // I have no idea how this works...
audioSource.PlayOneShot(shootingSound, 0.2f);
if (bullet != null) // If there is a bullet, use the seek method from the bullet script.
{
bullet.Seek(target);
}
}
void OnDrawGizmosSelected() // Do this method if gizmo is selected.
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, range); // Draw a wire sphere on the selected point (selected turret f. e.) and give it the towers range.
}
}
The problem was that i had a script called "GameObject" in my Unity Project.
I was also able to rename all "UnityEngine.GameObject" to "Gameobject" by using the Quick Action in Visual Studio.

Unity 2D: How to collide with side of screen

I'm working currently at a 2D Game for Android. There is a player in my scene and if the user tilts his device the player Object is moving on the ground. But he is just moving out of the screen at the left and the right side. I tried to make a "wall" but I had no success. At my player-Gameobject there is an edge collider. Now my question is: how can my player gameobject collide with the side of the screen?
This is my code:
public GameObject player;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
Vector3 dir = Vector3.zero;
dir.y = Input.acceleration.x;
player.transform.Translate(new Vector2(dir.y, 0) * Time.deltaTime * 2000f);
}
Thank you very much! :)
Jul
EDIT:
Image 1 is my Wall's and Image 2 my Player's.
I'm trying to solve it with a wall at the side of the screen. These are the images of
Solved
Solution code:
Vector3 position = player.transform.position;
translation = Input.acceleration.x * movementSpeed * 50f;
if (player.transform.position.x + translation < LeftlimitScreen)
{
position.x = -LeftlimitScreen;
}
else if(transform.position.x + translation > RightlimitScreen)
{
position.x = RightlimitScreen;
}
else
{
position.x += translation;
player.transform.position = position;
}
This code is working for me! :)
This will generate edge colliders around the screen (for 2d):
void GenerateCollidersAcrossScreen()
{
Vector2 lDCorner = camera.ViewportToWorldPoint(new Vector3(0, 0f, camera.nearClipPlane));
Vector2 rUCorner = camera.ViewportToWorldPoint(new Vector3(1f, 1f, camera.nearClipPlane));
Vector2[] colliderpoints;
EdgeCollider2D upperEdge = new GameObject("upperEdge").AddComponent<EdgeCollider2D>();
colliderpoints = upperEdge.points;
colliderpoints[0] = new Vector2(lDCorner.x, rUCorner.y);
colliderpoints[1] = new Vector2(rUCorner.x, rUCorner.y);
upperEdge.points = colliderpoints;
EdgeCollider2D lowerEdge = new GameObject("lowerEdge").AddComponent<EdgeCollider2D>();
colliderpoints = lowerEdge.points;
colliderpoints[0] = new Vector2(lDCorner.x, lDCorner.y);
colliderpoints[1] = new Vector2(rUCorner.x, lDCorner.y);
lowerEdge.points = colliderpoints;
EdgeCollider2D leftEdge = new GameObject("leftEdge").AddComponent<EdgeCollider2D>();
colliderpoints = leftEdge.points;
colliderpoints[0] = new Vector2(lDCorner.x, lDCorner.y);
colliderpoints[1] = new Vector2(lDCorner.x, rUCorner.y);
leftEdge.points = colliderpoints;
EdgeCollider2D rightEdge = new GameObject("rightEdge").AddComponent<EdgeCollider2D>();
colliderpoints = rightEdge.points;
colliderpoints[0] = new Vector2(rUCorner.x, rUCorner.y);
colliderpoints[1] = new Vector2(rUCorner.x, lDCorner.y);
rightEdge.points = colliderpoints;
}
You can place in your scene, outside of the region which will be displayed in your device 2 empty game objects with a collider, so the player will crash against them.
You can also limit by code the boundaries within the player can move. You apply this using Mathf.Clamp(), and there you will need to set the boundaries in the x coordinate for your scene.
You will see that instead of modifying the position of the player using its transform, we use the rigidbody instead.
public class PlayerController : MonoBehaviour
{
public float speed;
public float tilt;
public Boundary boundary;
void FixedUpdate ()
{
float moveHorizontal = Input.GetAxis ("Horizontal");
float moveVertical = Input.GetAxis ("Vertical");
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
rigidbody.velocity = movement * speed;
rigidbody.position = new Vector3
(
Mathf.Clamp (rigidbody.position.x, boundary.xMin, boundary.xMax),
0.0f,
5.0f
);
}
}
You can check the whole tutorial here: https://unity3d.com/earn/tutorials/projects/space-shooter/moving-the-player?playlist=17147
Update Other options:
//You select here the speed you consider
float speed = 1.0f;
void Update () {
Vector3 dir = Vector3.zero;
float InputValue = Input.acceleration.x * speed;
//You need to set the values for this limits (max and min) based on your scene
dir.y = Mathf.Clamp(InputValue, 0.5f, 50.5f);
player.transform.position = dir;
}
Update 2:
Without Clamp, just setting the limits on the script
void Update () {
Vector3 position = player.transform.position ;
translation = Input.acceleration.x * speed;
if( player.transform.position.y + translation < leftLimitScreen )
position.y = -leftLimitScreen ;
else if( myTransform.position.x + translation > rightLimitScreen )
position.y = rightLimitScreen ;
else
position.y += translation ;
player.transform.position = position ;
}
In a prototype i'm creating the solution i had arrived was creating "walls" with objects without sprites in the borders and checking if there is something there with Raycast with a script like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour {
RaycastHit2D[] hit;
Vector2[] directions;
private Vector2 targetPosition;
private float moveSpeed;
private float moveHDir;
private float wallPos;
private bool hitLeft;
private bool hitRight;
// Use this for initialization
void Start () {
directions = new Vector2[2] {Vector2.right, Vector2.left};
hitLeft = false;
hitRight = false;
}
// Update is called once per physics timestamp
void FixedUpdate () {
foreach (Vector2 dir in directions) {
hit = Physics2D.RaycastAll(transform.position, dir);
Debug.DrawRay(transform.position, dir);
if (hit[1].collider != null) {
// Keyboard control
if (Input.GetAxisRaw("Horizontal") != 0) {
moveHDir = Input.GetAxisRaw("Horizontal");
// I have found that a 5% of the size of the object it's a
// good number to set as a minimal distance from the obj to the borders
if (hit[1].distance <= (transform.localScale.x * 0.55f)) {
if (dir == Vector2.left) {
hitLeft = true;
} else {
hitRight = true;
}
wallPos = hit[1].collider.transform.position.x;
// Condition that guarantee that the paddle do not pass the borders of the screen
// but keeps responding if you try to go to the other side
if ((wallPos > this.transform.position.x && moveHDir < 0) ||
(wallPos < this.transform.position.x && moveHDir > 0)) {
moveSpeed = gControl.initPlayerSpeed;
} else {
moveSpeed = 0;
}
} else {
if (dir == Vector2.left) {
hitLeft = false;
} else {
hitRight = false;
}
if (!hitRight && !hitLeft)
{
moveSpeed = gControl.initPlayerSpeed;
}
}
}
}
}
targetPosition = new Vector2((transform.position.x + (moveSpeed * moveHDir)), transform.position.y);
}
}
Maybe it's not the best solution or the shortest one, but it's working wonders to me.
Good luck.
In case if you want to generate collider on the borders of the canvas (2D)
Attach this script in the main canvas object.
using UnityEngine;
public class BorderCollider: MonoBehaviour
{
private EdgeCollider2D _edgeCollider2D;
private Rigidbody2D _rigidbody2D;
private Canvas _canvas;
private float y, x;
private Vector2 _topLeft, _topRight, _bottomLeft, _bottomRight;
private void Start() {
//Adding Edge Collider
_edgeCollider2D = gameObject.AddComponent<EdgeCollider2D>();
//Adding Rigid body as a kinematic for collision detection
_rigidbody2D = gameObject.AddComponent<Rigidbody2D>();
_rigidbody2D.bodyType = RigidbodyType2D.Kinematic;
//Assigning canvas
_canvas = GetComponent<Canvas>();
GetCanvasDimension(); // Finds height and width fo the canvas
GetCornerCoordinate(); // Finds co-ordinate of the corners as a Vector2
DrawCollider(); // Draws Edge collide around the corners of canvas
}
public void GetCornerCoordinate() {
// Assign corners coordinate in the variables
_topLeft = new Vector2(-x,y); // Top Left Corner
_topRight = new Vector2(x,y); // Top Right Corner
_bottomLeft = new Vector2(-x,-y); // Bottom Left Corner
_bottomRight = new Vector2(x,-y); // Bottom Right Corner
}
void GetCanvasDimension(){
y = (_canvas.GetComponent<RectTransform>().rect.height) / 2;
x = (_canvas.GetComponent<RectTransform>().rect.width) / 2;
}
void DrawCollider() {
_edgeCollider2D.points = new[] {_topLeft, _topRight, _bottomRight, _bottomLeft,_topLeft};
}
}

Why are my characters flipping through the floor?

I am working on a simple patrol script, and everything works but the characters are randomly rolling through the floor when they turn around. Here is a short clip of them...
Here is my script...
public class Patrol : MonoBehaviour
{
public float speed = 5;
public float directionChangeInterval = 1;
public float maxHeadingChange = 30;
public bool useRootMotion;
CharacterController controller;
float heading;
Vector3 targetRotation;
Vector3 forward
{
get { return transform.TransformDirection(Vector3.forward); }
}
void Awake()
{
controller = GetComponent<CharacterController>();
// Set random initial rotation
heading = Random.Range(0, 360);
transform.eulerAngles = new Vector3(0, heading, 0);
StartCoroutine(NewHeadingRoutine());
}
void Update()
{
transform.eulerAngles = Vector3.Slerp(transform.eulerAngles, targetRotation, Time.deltaTime * directionChangeInterval);
if (useRootMotion)
{
return;
}
else
{
controller.SimpleMove(forward * speed);
}
}
void OnControllerColliderHit(ControllerColliderHit hit)
{
if (hit.gameObject.tag == "Player")
{
// Bounce off the obstacle and change direction
var newDirection = Vector3.Reflect(forward, hit.normal);
transform.rotation = Quaternion.FromToRotation(Vector3.forward, newDirection);
heading = transform.eulerAngles.y;
NewHeading();
}
if (hit.gameObject.tag == "Boundary")
{
// Bounce off the obstacle and change direction
var newDirection = Vector3.Reflect(forward, hit.normal);
transform.rotation = Quaternion.FromToRotation(Vector3.forward, newDirection);
heading = transform.eulerAngles.y;
NewHeading();
}
}
/// Finds a new direction to move towards.
void NewHeading()
{
var floor = transform.eulerAngles.y - maxHeadingChange;
var ceil = transform.eulerAngles.y + maxHeadingChange;
heading = Random.Range(floor, ceil);
targetRotation = new Vector3(0, heading, 0);
}
/// Repeatedly calculates a new direction to move towards.
IEnumerator NewHeadingRoutine()
{
while (true)
{
NewHeading();
yield return new WaitForSeconds(directionChangeInterval);
}
}
}
I have tried adding a rigidbody to the characters and constraining rotation, but that doesnt work. Oddly enough, the character control isnt rotating at all. In the scene view I can see the character collider staying as it should, but the character flips through the mesh on its own.
It looks like it's because they are walking into a corner and being bounced between the two walls constantly which causes them to behave strangely. I would add a method of checking for a series of very quick collisions to detect that they are in a corner or stuck and then adapt accordingly, perhaps with a method to rotate 180 degrees and keep walking or the like.
You can do it like this:
float fTime = 0.1f
float fTimer = 0;
int iCollisionCounter;
if(collision){
if(fTimer > 0) iCollisionCounter++;
if(iCollisionCounter >= 5) //Character is stuck
fTimer = fTime;
}
Void Update(){
fTimer -= time.deltaTime;
}
That means that if there are multiple collisions within 0.1 seconds of each other you can handle it.
Hope this helps!

Unity3D : make cylinder stretch from one point to another

I'd like, at each frame, to move, scale and rotate a given cylinder so that it behaves like a 'rope' between two points.
I have this code at the moment, but it doesn't work at all like intended :
hook.transform.position = (rightHandPosition + hookDestination)/2;
hook.transform.localScale = new Vector3(0.5F, Vector3.Magnitude(hookDestination - rightHandPosition), 0.5F);
hook.transform.rotation = Quaternion.Euler(hookDestination - rightHandPosition);
As you can guess the two points are rightHandPosition and hookDestination. For now, the cylinder spawns at 'random' locations, with 'random' rotations and enormous scales.
How can I fix it ?
"Full" script :
public class FirstPersonController : MonoBehaviour {
public GameObject hook;
bool isHooked = false;
Vector3 hookDestination;
Vector3 rightHandPosition;
void Start() {
hook.renderer.enabled = false;
rightHandPosition = hook.transform.position;
}
// Update is called once per frame
void Update () {
if (isHooked) {
hook.transform.position = (rightHandPosition + hookDestination)/2;
hook.transform.localScale = new Vector3(0.5F, Vector3.Magnitude(hookDestination - rightHandPosition), 0.5F);
hook.transform.rotation = Quaternion.Euler(hookDestination - rightHandPosition);
}
if (isHooked && !Input.GetMouseButton(1)) {
isHooked = false;
hook.renderer.enabled = false;
}
if (Input.GetMouseButtonDown (1) && !isHooked) {
Ray ray = GameObject.FindGameObjectWithTag ("MainCamera").camera.ViewportPointToRay (new Vector3 (0.5F, 0.5F, 0));
RaycastHit hit;
if (Physics.Raycast (ray, out hit) && hit.distance < 5000000 && hit.collider.tag != "Player") {
isHooked = true;
hookDestination = hit.point;
hook.renderer.enabled = true;
}
}
}
}
A screenshot of the scene :
fafase's comment was the right answer : use LineRenderer.
hookRender.SetPosition(0, rightHandPosition);
hookRender.SetPosition(1, hookDestination);
Let us assume that cubeStart is the starting point and cubeEnd is the end point. And "cylinder" is your cylinder, then
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AlignCyl : MonoBehaviour {
GameObject cubeStart;
GameObject cubeEnd;
GameObject cylinder;
Vector3 endV;
Vector3 startV;
Vector3 rotAxisV;
Vector3 dirV;
Vector3 cylDefaultOrientation = new Vector3(0,1,0);
float dist;
// Use this for initialization
void Start () {
cubeStart = GameObject.Find("CubeStart");
cubeEnd = GameObject.Find("CubeEnd");
cylinder = GameObject.Find("Cylinder");
endV = cubeEnd.transform.position;
startV = cubeStart.transform.position;
}
// Update is called once per frame
void Update () {
// Position
cylinder.transform.position = (endV + startV)/2.0F;
// Rotation
dirV = Vector3.Normalize(endV - startV);
rotAxisV = dirV + cylDefaultOrientation;
rotAxisV = Vector3.Normalize(rotAxisV);
cylinder.transform.rotation = new Quaternion(rotAxisV.x, rotAxisV.y, rotAxisV.z, 0);
// Scale
dist = Vector3.Distance(endV, startV);
cylinder.transform.localScale = new Vector3(1, dist/2, 1);
}
}
Tested with Unity3D 2018.1
My concept about rotation is based on quaternions solely.
x=rotAxis.x * sin(angle/2) = rotAxis.x;
y=rotAxis.y * sin(angle/2) = rotAxis.y;
z=rotAxis.z * sin(angle/2) = rotAxis.z;
w = cos(angle/2) = 0;
where rotAxis is the sum of 2 vectors i.e. the default cylinder orientation and the wanted orientation. Angle is 180 degrees because we want the cylinder to rotate around the rotAxis by 180 degrees. It is the definition of quaternion rotation (rotation around an axis).

In Unity3D, what is the best way to offset the viewport with multiple resolutions so the player is always to the left edge?

I'm working on my latest project, which is a action sidescroller, primarily 2D but using a perspective camera for 3D effect. I've gotten the basics working - design, etc, and now fixing the camera so that it follows correctly. However, I'd like to keep the player on the left side of the viewport - not actually modifying the player's position, but the camera following an offset. I have it partially worked out, but it broke the moment I started playing around with other alternative resolutions - say, from web standard, standalone, to mobile devices. This is what I want to do:
This is my code attempt thus far. The camera itself works perfectly for basic up/down right scrolling, but when the resolution changes the player can vanish:
public Transform TrackTarget;
public float dampTime = 0.15f;
public bool Ready = false;
private Vector3 velocity = Vector3.zero;
private Vector3 TargetOffset = Vector3.zero;
void Start()
{
TargetOffset = new Vector3(16,0,0);
Vector3 point = TrackTarget.position + TargetOffset;
Vector3 Destination = new Vector3(point.x, transform.position.y, transform.position.x);
transform.position = Destination;
}
void FixedUpdate () {
if (Ready) {
if (TrackTarget)
{
Vector3 point = TrackTarget.position + TargetOffset;
Vector3 Destination = new Vector3(point.x, transform.position.y, transform.position.x);
transform.position = Vector3.SmoothDamp(transform.position, Destination, ref velocity, dampTime);
}
}
}
void LateUpdate()
{
if (Ready) {
Vector3 CameraPosition = transform.position;
CameraPosition.z = -30.00f;
transform.position = CameraPosition;
}
}
This may be helpful.
public class CameraController : MonoBehaviour {
public Transform target;
public float distance = 5;
public float heigt = 1;
public float width = 6;
public float damping = 5;
void Start()
{
Vector3 unicornPos = camera.WorldToViewportPoint(target.position);
width = camera.ViewportToWorldPoint(new Vector3(1, 1, camera.nearClipPlane)).x/3;
}
void LateUpdate () {
Vector3 wantedPosition = target.TransformPoint (width, heigt, -distance);
transform.position = Vector3.Lerp (transform.position, wantedPosition, Time.deltaTime * damping);
}
}

Categories

Resources