Script para hacer cuerdas & Novedades en la web
24 Noviembre 2009
Aqui teneis el primer artículo como muestra de la evolución que esta sufriendo la web. Como algunos habreis visto en el foro he puesto que necesitamos un redactor, hasta que tengamos uno, yo haré sus funciones.
La necesidad de un redactor nace de querer ofreceros algo más que una comunidad, poco a poco vamos avanzando con nuevas secciones, como la sección de utilidades a punto de ser remodelada, o la nueva tienda; el siguiente paso es ofreceros más mejores contenidos por eso, a partir de ahora, y espero que con bastante frecuencia publicare un artículo sobre unity, normalmente extraido de los foros de unity que me parezca interesante.

Alguno pensareis que esto mismo lo podría hacer en el foro, pero no es ese el enfoque que quiero dar a esta novedad, quiero que la portada de la web sea un punto de referencia, y el foro, un punto de reunión virtual para todos nosotros.
Sin dar mas la brasa, os dejo con el artículo de hoy, me parece muy bueno, esta sacado de los foros de unity y consiste en un script para hacer cuedas o materiales similares en unity. Lo tenéis completo en Leer Más.
El script en concreto, encontrado en el foro oficial de unity me parece muy interesante ya que permite hacer cuerdas, cables o tubos con un tamaño personalizado, asi como número de segmentos y otras propiedades, todo ello sometido a las físicas de unity.

Para ello necesitais tener en vuestro proyecto este script:
/*==========================
== Physics Based 3D Rope ==
== File: Rope_Tube.js ==
== By: Jacob Fletcher ==
== Use and alter Freely ==
============================
How To Use:
( BASIC )
1. Simply add this script to the object you want a rope teathered to
3. Assign the other end of the rope as the "Target" object in this script
4. Play and enjoy!
(About Character Joints)
Sometimes your rope needs to be very limp and by that I mean NO SPRINGY EFFECT.
In order to do this, you must loosen it up using the swingAxis and twist limits.
For example, On my joints in my drawing app, I set the swingAxis to (0,0,1) sense
the only axis I want to swing is the Z axis (facing the camera) and the other settings to around -100 or 100.
*/
var target : Transform;
var material : Material;
var ropeWidth = 0.5;
var resolution = 0.5;
var ropeDrag = 0.1;
var ropeMass = 0.5;
var radialSegments = 6;
var startRestrained = true;
var endRestrained = false;
var useMeshCollision = false;
// Private Variables (Only change if you know what your doing)
private var segmentPos : Vector3[];
private var joints : GameObject[];
private var tubeRenderer : GameObject;
private var line;
private var segments = 4;
private var rope = false;
//Joint Settings
var swingAxis = Vector3(0,1,0);
var lowTwistLimit = 0.0;
var highTwistLimit = 0.0;
var swing1Limit = 20.0;
// Require a Rigidbody
@script RequireComponent(Rigidbody)
function OnDrawGizmos() {
if(target) {
Gizmos.color = Color.yellow;
Gizmos.DrawLine (transform.position, target.position);
Gizmos.DrawWireSphere ((transform.position+target.position)/2,ropeWidth);
Gizmos.color = Color.green;
Gizmos.DrawWireSphere (transform.position, ropeWidth);
Gizmos.color = Color.red;
Gizmos.DrawWireSphere (target.position, ropeWidth);
} else {
Gizmos.color = Color.green;
Gizmos.DrawWireSphere (transform.position, ropeWidth);
}
}
function Awake()
{
if(target) {
BuildRope();
} else {
Debug.LogError("You must have a gameobject attached to target: " + this.name,this);
}
}
function LateUpdate()
{
if(target) {
// Does rope exist? If so, update its position
if(rope) {
line.SetPoints(segmentPos, ropeWidth, Color.white);
line.enabled = true;
segmentPos[0] = transform.position;
for(s=1;s<segments;s++)
{
segmentPos[s] = joints[s].transform.position;
}
}
}
}
function BuildRope()
{
tubeRenderer = new GameObject("TubeRenderer_" + gameObject.name);
line = tubeRenderer.AddComponent(TubeRenderer);
line.useMeshCollision = useMeshCollision;
// Find the amount of segments based on the distance and resolution
// Example: [resolution of 1.0 = 1 joint per unit of distance]
segments = Vector3.Distance(transform.position,target.position)*resolution;
if(material) {
material.SetTextureScale("_MainTex",Vector2(1,segments+2));
if(material.GetTexture("_BumpMap"))
material.SetTextureScale("_BumpMap",Vector2(1,segments+2));
}
line.vertices = new TubeVertex[segments];
line.crossSegments = radialSegments;
line.material = material;
segmentPos = new Vector3[segments];
joints = new GameObject[segments];
segmentPos[0] = transform.position;
segmentPos[segments-1] = target.position;
// Find the distance between each segment
var segs = segments-1;
var seperation = ((target.position - transform.position)/segs);
for(s=0;s < segments;s++)
{
// Find the each segments position using the slope from above
vector = (seperation*s) + transform.position;
segmentPos[s] = vector;
//Add Physics to the segments
AddJointPhysics(s);
}
// Attach the joints to the target object and parent it to this object
var end = target.gameObject.AddComponent("CharacterJoint");
end.connectedBody = joints[joints.length-1].transform.rigidbody;
end.swingAxis = swingAxis;
end.lowTwistLimit.limit = lowTwistLimit;
end.highTwistLimit.limit = highTwistLimit;
end.swing1Limit.limit = swing1Limit;
target.parent = transform;
if(endRestrained)
{
end.rigidbody.isKinematic = true;
}
if(startRestrained)
{
transform.rigidbody.isKinematic = true;
}
// Rope = true, The rope now exists in the scene!
rope = true;
}
function AddJointPhysics(n)
{
joints[n] = new GameObject("Joint_" + n);
joints[n].transform.parent = transform;
var rigid = joints[n].AddComponent("Rigidbody");
if(!useMeshCollision) {
var col = joints[n].AddComponent("SphereCollider");
col.radius = ropeWidth;
}
var ph = joints[n].AddComponent("CharacterJoint");
ph.swingAxis = swingAxis;
ph.lowTwistLimit.limit = lowTwistLimit;
ph.highTwistLimit.limit = highTwistLimit;
ph.swing1Limit.limit = swing1Limit;
//ph.breakForce = ropeBreakForce; <--------------- TODO
joints[n].transform.position = segmentPos[n];
rigid.drag = ropeDrag;
rigid.mass = ropeMass;
if(n==0){
ph.connectedBody = transform.rigidbody;
} else
{
ph.connectedBody = joints[n-1].rigidbody;
}
}
Y este es el script para realizar cuerdas:
/*
TubeRenderer.js
This script is created by Ray Nothnagel of Last Bastion Games. It is
free for use and available on the Unify Wiki.
For other components I've created, see:
http://lastbastiongames.com/middleware/
(C) 2008 Last Bastion Games
--------------------------------------------------------------
EDIT: MODIFIED BY JACOB FLETCHER FOR USE WITH THE ROPE SCRIPT
http://www.reverieinteractive.com
*/
class TubeVertex {
var point : Vector3 = Vector3.zero;
var radius : float = 1.0;
var color : Color = Color.white;
function TubeVertex(pt : Vector3, r : float, c : Color) {
point=pt;
radius=r;
color=c;
}
}
var vertices : TubeVertex[];
var material : Material;
var crossSegments : int = 3;
var flatAtDistance : float=-1;
var movePixelsForRebuild = 6;
var maxRebuildTime = 0.1;
var useMeshCollision = false;
private var lastCameraPosition1 : Vector3;
private var lastCameraPosition2 : Vector3;
private var crossPoints : Vector3[];
private var lastCrossSegments : int;
private var lastRebuildTime = 0.00;
private var mesh;
private var colliderExists = false;
private var usingBumpmap = false;
function Reset() {
vertices = [TubeVertex(Vector3.zero, 1.0, Color.white), TubeVertex(Vector3(1,0,0), 1.0, Color.white)];
}
function Start() {
Reset();
mesh = new Mesh();
gameObject.AddComponent(MeshFilter);
var mr : MeshRenderer = gameObject.AddComponent(MeshRenderer);
mr.material = material;
if(material) {
if(material.GetTexture("_BumpMap")) usingBumpmap = true;
}
}
function LateUpdate () {
if (!vertices || vertices.length <= 1) {
renderer.enabled=false;
return;
}
renderer.enabled=true;
if (crossSegments != lastCrossSegments) {
crossPoints = new Vector3[crossSegments];
var theta : float = 2.0*Mathf.PI/crossSegments;
for (c=0;c<crossSegments;c++) {
crossPoints[c] = Vector3(Mathf.Cos(theta*c), Mathf.Sin(theta*c), 0);
}
lastCrossSegments = crossSegments;
}
var meshVertices : Vector3[] = new Vector3[vertices.length*crossSegments];
var uvs : Vector2[] = new Vector2[vertices.length*crossSegments];
var colors : Color[] = new Color[vertices.length*crossSegments];
var tris : int[] = new int[vertices.length*crossSegments*6];
var lastVertices : int[] = new int[crossSegments];
var theseVertices : int[] = new int[crossSegments];
var rotation : Quaternion;
for (p=0;p<vertices.length;p++) {
if(p<vertices.length-1)
rotation = Quaternion.FromToRotation(Vector3.forward,vertices[p+1].point-vertices[p].point);
for (c=0;c<crossSegments;c++) {
var vertexIndex : int = p*crossSegments+c;
meshVertices[vertexIndex] = vertices[p].point + rotation * crossPoints[c] * vertices[p].radius;
uvs[vertexIndex] = Vector2((0.0+c)/crossSegments,(0.0+p)/vertices.length);
colors[vertexIndex] = vertices[p].color;
lastVertices[c]=theseVertices[c];
theseVertices[c] = p*crossSegments+c;
}
//make triangles
if (p>0) {
for (c=0;c<crossSegments;c++) {
var start : int= (p*crossSegments+c)*6;
tris[start] = lastVertices[c];
tris[start+1] = lastVertices[(c+1)%crossSegments];
tris[start+2] = theseVertices[c];
tris[start+3] = tris[start+2];
tris[start+4] = tris[start+1];
tris[start+5] = theseVertices[(c+1)%crossSegments];
}
}
}
//Clear mesh for new build (jf)
mesh.Clear();
mesh.vertices = meshVertices;
mesh.triangles = tris;
mesh.RecalculateNormals();
if(usingBumpmap)
mesh.tangents = CalculateTangents(meshVertices);
mesh.uv = uvs;
if(useMeshCollision)
if(colliderExists) {
gameObject.GetComponent(MeshCollider).sharedMesh = mesh;
} else {
gameObject.AddComponent(MeshCollider);
colliderExists = true;
}
GetComponent(MeshFilter).mesh = mesh;
}
function CalculateTangents(verts)
{
var tangents = new Vector4[verts.length];
for(i=0;i<tangents.length;i++)
{
var vertex1 = i > 0 ? verts[i-1] : verts[i];
var vertex2 = i < tangents.length - 1 ? verts[i+1] : verts[i];
var tan = (vertex1 - vertex2).normalized;
tangents[i] = Vector4( tan.x, tan.y, tan.z, 1.0 );
}
return tangents;
}
//sets all the points to points of a Vector3 array, as well as capping the ends.
function SetPoints(points : Vector3[], radius : float, col : Color) {
if (points.length < 2) return;
vertices = new TubeVertex[points.length+2];
var v0offset : Vector3 = (points[0]-points[1])*0.01;
vertices[0] = TubeVertex(v0offset+points[0], 0.0, col);
var v1offset : Vector3 = (points[points.length-1] - points[points.length-2])*0.01;
vertices[vertices.length-1] = TubeVertex(v1offset+points[points.length-1], 0.0, col);
for (p=0;p<points.length;p++) {
vertices[p+1] = TubeVertex(points[p], radius, col);
}
}
Os explico las intrucciones para el que no entienda o no quiera entender el ingles. El sistema es sencillo, teneis que añadir el script al objeto, ya sea vacio, o sea un elemento de la escena; este será el origen de la cuerda. En el inspector, dentro de las variables públicas podreis seleccionar el objeto que sea destino de la cuerda. También podeis modificar otros atributos como el material, la elasticidad....

Espero que os haya gustado este primer artículo del nuevo enfoque de la web, en cuanto pueda más, y espero que mejor. Podeis comentar aqui directamente o en el foro.