Latest Threads |
Obi 7 Questions
Forum: Obi Cloth
Last Post: MEPETAMINALS
Today, 12:14 AM
» Replies: 2
» Views: 46
|
Rope extension, vibration...
Forum: Obi Rope
Last Post: 0hsyn1
19-04-2025, 10:15 AM
» Replies: 2
» Views: 83
|
How to increase stiffness...
Forum: Obi Softbody
Last Post: josemendez
17-04-2025, 08:57 AM
» Replies: 1
» Views: 105
|
Collision Between 2 SoftB...
Forum: Obi Softbody
Last Post: josemendez
16-04-2025, 01:38 PM
» Replies: 3
» Views: 3,745
|
Issues trying to trap obj...
Forum: Obi Cloth
Last Post: josemendez
14-04-2025, 08:54 AM
» Replies: 3
» Views: 244
|
How to fix both ends when...
Forum: Obi Rope
Last Post: josemendez
12-04-2025, 02:17 PM
» Replies: 5
» Views: 597
|
How can I make my ropes n...
Forum: Obi Rope
Last Post: josemendez
07-04-2025, 01:57 PM
» Replies: 1
» Views: 184
|
Problem with softbody and...
Forum: Obi Softbody
Last Post: josemendez
03-04-2025, 10:05 AM
» Replies: 13
» Views: 4,527
|
Updating softbody vertex ...
Forum: Obi Softbody
Last Post: Aroosh
03-04-2025, 08:17 AM
» Replies: 2
» Views: 324
|
How can I detect my secon...
Forum: Obi Rope
Last Post: josemendez
03-04-2025, 08:16 AM
» Replies: 9
» Views: 1,005
|
|
|
Obi 7 Questions |
Posted by: MEPETAMINALS - Yesterday, 06:56 PM - Forum: Obi Cloth
- Replies (2)
|
 |
Hi, I've been heavily using Obi (cloth and rope) for several years now in the development of Following Seas. I'm quite happy with it overall, with really the biggest issue coming down to performance. Typically about 30-50% of total profiler load goes into the system -- which has been acceptable, but definitely reduces the number of runnable systems for users.
I've been looking into Obi 7, as performance seems to be a major focus, and have also split into a separate project branch to test it out -- but have a couple questions if you don't mind.
I'm struggling with the removal of Proxies -- are there any plans for a similar system, or revisions to the decimation? I like the automatic decimation, but I find that there isn't near the control that was available with proxies. For example, my cloth meshes rely on specific groups for attachment points, like the rays of a battened sail, or the corners where ropes would attach. Decimation on my more detailed meshes often causes these points to be far off from where they should be, or causes topology lines to become very wobbly due to merging inconsistently up and down when parallel lines of vertices are present. It would be nice to exclude vertex groups from decimation, or have a method of ensuring the shape of the mesh isn't overly affected.
I didn't see any method for controlling this, do you have any suggestions?
Secondly, it seems that ambient force zones have been removed -- is it preferred to have a wind force zone follow affected objects around, or to set wind directly through the solver?
I've attached a beautifully rendered version of my struggle with blueprints. The left indicates the result gained via the Obi 6 method, with the red dots representing vertices on the simplified mesh. The central black line is a group used for particle attachment, and the red corner is a point were a rope would attach.
On the right is a somewhat dramatized example of what I'm encountering through decimation.
|
|
|
Rope extension, vibration and collision |
Posted by: 0hsyn1 - 19-04-2025, 08:00 AM - Forum: Obi Rope
- Replies (2)
|
 |
Hello,
I am developing a project using the system in your Hook project as a reference. I can lengthen and shorten the rope, but the rope has problems interacting with colliders, as far as I understand the particle count is low. How can I increase this? If my method is wrong, please tell me.
When I wrap it around an obstacle, the rope vibrates.
Example of the project I am trying to make: https://play.google.com/store/apps/detai...lley&pli=1
Point A is fixed, point B is moveable.
Thank you 
Code: using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Obi;
using System;
public class RopeCreate : MonoBehaviour
{
[Header("Obi")]
[SerializeField] Transform ropeEnd;
public ObiSolver solver;
public ObiCollider2D character;
public float hookExtendRetractSpeed = 2;
public Material material;
public ObiRopeSection section;
private ObiRope rope;
private ObiRopeBlueprint blueprint;
private ObiRopeExtrudedRenderer ropeRenderer;
private ObiRopeCursor cursor;
private RaycastHit hookAttachment;
public Rigidbody2D characterRb;
void Awake()
{
// Create both the rope and the solver:
rope = gameObject.AddComponent<ObiRope>();
ropeRenderer = gameObject.AddComponent<ObiRopeExtrudedRenderer>();
ropeRenderer.section = section;
ropeRenderer.uvScale = new Vector2(1, 5);
ropeRenderer.normalizeV = false;
ropeRenderer.uvAnchor = 1;
rope.GetComponent<MeshRenderer>().material = material;
// Setup a blueprint for the rope:
blueprint = ScriptableObject.CreateInstance<ObiRopeBlueprint>();
blueprint.resolution = 0.5f;
// Tweak rope parameters:
rope.maxBending = 0.02f;
// Add a cursor to be able to change rope length:
cursor = rope.gameObject.AddComponent<ObiRopeCursor>();
cursor.cursorMu = 0;
cursor.direction = true;
}
private void Start()
{
if (!rope.isLoaded)
LaunchHook();
Debug.Log(GetRopeLength());
}
private void OnDestroy()
{
DestroyImmediate(blueprint);
}
/**
* Raycast against the scene to see if we can attach the hook to something.
*/
private void LaunchHook()
{
StartCoroutine(AttachHook());
}
private IEnumerator AttachHook()
{
yield return null;
Vector3 startLocal = transform.position;
Vector3 endLocal = ropeEnd.position;
Vector3 direction = (endLocal - startLocal).normalized;
blueprint.path.Clear();
blueprint.path.AddControlPoint(startLocal, -direction, direction, Vector3.up, 0.1f, 0.1f, 1, 1, Color.white, "Hook start");
blueprint.path.AddControlPoint(endLocal, -direction, direction, Vector3.up, 0.1f, 0.1f, 1, 1, Color.white, "Hook end");
blueprint.path.FlushEvents();
yield return blueprint.Generate();
rope.ropeBlueprint = blueprint;
rope.GetComponent<MeshRenderer>().enabled = true;
var pinConstraints = rope.GetConstraintsByType(Oni.ConstraintType.Pin) as ObiConstraints<ObiPinConstraintsBatch>;
pinConstraints.Clear();
var batch = new ObiPinConstraintsBatch();
batch.AddConstraint(rope.solverIndices[0], character, transform.localPosition, Quaternion.identity, 0, 0, float.PositiveInfinity);
batch.AddConstraint(rope.solverIndices[blueprint.activeParticleCount - 1],
ropeEnd.GetComponent<ObiColliderBase>(),
//ropeEnd.position,
//ropeEnd.InverseTransformPoint(ropeStart.position),
Vector3.zero,
Quaternion.identity, 0, 0, float.PositiveInfinity);
batch.activeConstraintCount = 2;
pinConstraints.AddBatch(batch);
rope.SetConstraintsDirty(Oni.ConstraintType.Pin);
}
public void RopeIncrease()
{
cursor.ChangeLength(rope.restLength + hookExtendRetractSpeed * Time.deltaTime);
}
public void RopeDecrease()
{
cursor.ChangeLength(rope.restLength - hookExtendRetractSpeed * Time.deltaTime );
}
public float GetStrain()
{
float strain = rope.restLength / rope.CalculateLength();
return strain;
}
public float GetRopeLength()
{
return rope.CalculateLength();
}
}
Code: public class CapsuleMove : MonoBehaviour
{
[SerializeField]RopeCreate ropeCreate;
[Header("Move")]
const float speed = 500f;
private Vector3 mOffset;
private float mZCoord;
private bool active;
private Rigidbody2D rb;
float startRotation;
[SerializeField] public bool isRopeLengthMax = false;
public Vector2 startPos;
private Vector2 previousPosition;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void OnMouseDown()
{
mZCoord = Camera.main.WorldToScreenPoint(transform.position).z;
mOffset = transform.position - GetMouseAsWorldPoint();
active = true;
rb.velocity = Vector2.zero;
rb.gravityScale = 0f;
rb.constraints &= ~RigidbodyConstraints2D.FreezePositionX;
rb.constraints &= ~RigidbodyConstraints2D.FreezePositionY;
}
private void OnMouseUp()
{
MouseDownEnded();
}
private void MouseDownEnded()
{
active = false;
rb.gravityScale = 1f;
rb.velocity = Vector2.zero;
// rb.freezeRotation = true;
rb.constraints = RigidbodyConstraints2D.FreezePositionX | RigidbodyConstraints2D.FreezePositionY | RigidbodyConstraints2D.FreezeRotation;
}
private Vector3 GetMouseAsWorldPoint()
{
Vector3 mousePoint = Input.mousePosition;
mousePoint.z = mZCoord;
return Camera.main.ScreenToWorldPoint(mousePoint);
}
private void FixedUpdate()
{
if (isRopeLengthMax)
{
MouseDownEnded();
return;
}
if (active)
{
Vector2 desiredPosition = (Vector2)(GetMouseAsWorldPoint() + mOffset);
Vector2 direction = desiredPosition - rb.position;
rb.velocity = direction.magnitude > 0.1f ? direction * Time.fixedDeltaTime * speed : Vector2.zero;
float distanceMoved = Vector2.Distance(rb.position, previousPosition);
if (distanceMoved < 0.05f)
{
return;
}
if (ropeCreate.GetStrain() > .9)
{
ropeCreate.RopeDecrease();
}
else
{
ropeCreate.RopeIncrease();
// Debug.Log("Lenght" + ropeCreate.GetRopeLength());
}
previousPosition = rb.position;
}
}
}
|
|
|
How to increase stiffness? |
Posted by: softphysics - 16-04-2025, 07:27 PM - Forum: Obi Softbody
- Replies (1)
|
 |
I have a soft body that I want to attach to a 3d object. When I work at the scale I want (size of around 0.1 units), it has zero structural integrity. I tried decreasing the mass of the particles but that didn't work. If I work with meshes around size of 1, then I can attach the soft body to an object and it has some structural integrity but it still flops around too much. Tried tweaking lots of params (e.g. deformation resistance) but still the same. In older versions there was a control to increase connections between particles that has gone now. What I really want to achieve is to be able to interpolate between a rigid and a soft body, e.g. increase the stiffness of the spring programmatically between each particle. Can't see any kind of functionality like this exposed though. Any ideas?
|
|
|
How can I make my ropes not float upwards? |
Posted by: anthony_dev - 07-04-2025, 01:47 PM - Forum: Obi Rope
- Replies (1)
|
 |
Hello,
I am trying to figure out a way to have multiple pin points on my rope so I can move them like a snake.
I am unable to figure out what may cause this bug, my rope is floating on the non-kinematic end. For context, the selected object is a kinematic pin on my rope, the other golden balls are non-kinematic obi rigid bodies.
I am providing my solver settings alongside my result in the attachment.
Here's the code snippet I used to create the rope:
(It is messy but I use it for having pre-existing control points in the scene, and creating a rope blueprint and a rope out of these existing control points called "snake pieces")
Code: using System;
using System.Collections.Generic;
using System.Linq;
using _Game.Scripts.GameplayElements.Snakes;
using Obi;
using UnityEngine;
namespace _Game.Scripts.Gameplay.Demo
{
public class DemoSnake : MonoBehaviour
{
[SerializeField] private List<SnakePiece> snakePieces;
[SerializeField] private ObiSolver solver;
[SerializeField] private Material ropeMaterial;
[SerializeField] private ObiRopeSection ropeSection;
[SerializeField] private ObiCollisionMaterial collisionMaterial;
[SerializeField] private float ropeThickness;
[SerializeField] private ObiRope rope;
private ObiCollider[] Colliders => snakePieces.Select(o => o.GetComponent<ObiCollider>()).ToArray();
private void Start()
{
CreateSnake();
}
private void CreateSnake()
{
rope = CreateRopeProcedurally(this, Colliders, 0);
PinRope(rope, Colliders);
}
public void PinRope(ObiRope rope, params ObiCollider[] colliders)
{
PinRopeEnds(rope, colliders);
for (int i = 1; i < colliders.Length-1; i++)
{
var obiCollider = colliders[i];
var attachment = rope.gameObject.AddComponent<ObiParticleAttachment>();
attachment.attachmentType = ObiParticleAttachment.AttachmentType.Dynamic;
attachment.target = obiCollider.transform;
attachment.particleGroup = rope.ropeBlueprint.groups[i];
attachment.compliance = 0F;
}
}
public void PinRopeEnds(ObiRope rope, params ObiCollider[] colliders)
{
var colliderStart = colliders[0];
var colliderEnd = colliders[^1];
var startIndex = rope.ropeBlueprint.groups.FindIndex(g => g.name == "start");
var endIndex = rope.ropeBlueprint.groups.FindIndex(g => g.name == "end");
var attachmentStart = rope.gameObject.AddComponent<ObiParticleAttachment>();
attachmentStart.attachmentType = ObiParticleAttachment.AttachmentType.Dynamic;
attachmentStart.target = colliderStart.transform;
attachmentStart.particleGroup = rope.ropeBlueprint.groups[startIndex];
var attachmentEnd = rope.gameObject.AddComponent<ObiParticleAttachment>();
attachmentEnd.attachmentType = ObiParticleAttachment.AttachmentType.Dynamic;
attachmentEnd.target = colliderEnd.transform;
attachmentEnd.particleGroup = rope.ropeBlueprint.groups[endIndex];
}
public ObiRope CreateRopeProcedurally(DemoSnake snake, ObiCollider[] controlPoints, int index = 0)
{
var ropeObject = new GameObject($"Rope_{index}");
ropeObject.transform.parent = solver.transform;
var rope = ropeObject.AddComponent<ObiRope>();
var blueprint = CreateBlueprint(snake, controlPoints,out var length);
rope.ropeBlueprint = blueprint;
rope.distanceConstraintsEnabled = true;
rope.stretchingScale = 0.5f;
rope.surfaceCollisions = false;
rope.collisionMaterial = collisionMaterial;
rope.maxBending = 0.5f;
rope.bendCompliance = 1f;
rope.selfCollisions = true;
var ropeRenderer = ropeObject.AddComponent<ObiRopeExtrudedRenderer>();
ropeRenderer.material = ropeMaterial;
ropeRenderer.section = ropeSection;
var smoother = rope.GetComponent<ObiPathSmoother>();
smoother.decimation = 0.1f;
smoother.smoothing = 1;
var ropeReel = ropeObject.AddComponent<ObiRopeReel>();
ropeReel.enabled = false;
ropeReel.outThreshold = 0.08f;
ropeReel.inThreshold = 0.05f;
ropeReel.outSpeed = 6f;
ropeReel.inSpeed = 0.1f;
ropeReel.maxLength = Mathf.Max(1f, length);
var cursor = ropeObject.GetComponent<ObiRopeCursor>();
cursor.cursorMu = 0.05f;
cursor.sourceMu = 0.1f;
return rope;
}
public ObiRopeBlueprint CreateBlueprint(DemoSnake snake, ObiCollider[] points, out float distance)
{
distance = 0;
//Create the blueprint
var blueprint = ScriptableObject.CreateInstance<ObiRopeBlueprint>();
blueprint.resolution = 1f;
blueprint.thickness = 0.03f;
blueprint.pooledParticles = 0;
//Convert ropePoints to controlPoints
var controlPoints = new Vector3[points.Length];
blueprint.path.Clear();
blueprint.ClearParticleGroups();
var placeholder = Vector3.back * 1000;
for (int i = 0; i < controlPoints.Length; i++)
{
var point = points[i];
var controlPoint = snake.transform.InverseTransformPoint(point.transform.position);
controlPoints[i] = controlPoint;
Vector3 previousPoint =
i <= 0
? placeholder
: controlPoints[i - 1];
Vector3 nextPoint =
i >= controlPoints.Length - 1
? placeholder
: controlPoints[i + 1];
previousPoint = previousPoint != placeholder
? previousPoint
: controlPoint;
nextPoint = nextPoint != placeholder
? nextPoint
: controlPoint;
if(i != 0) distance += Vector3.Distance(previousPoint, controlPoint);
var inTangentVector = -(controlPoint - previousPoint) * 0.02f;
var outTangentVector = (nextPoint - controlPoint) * 0.02f;
blueprint.path.AddControlPoint(controlPoint, inTangentVector, outTangentVector,
Vector3.up, 0.1f, 0.1f, (i == 0 || i == controlPoints.Length-1 ? ropeThickness*0.8f : ropeThickness), 1, Color.white,
//i.ToString());
$"{(i == 0 ? "start" : i == controlPoints.Length - 1 ? "end" : i.ToString())}");
blueprint.path.filters[i] = ObiUtils.MakeFilter(-1, 0);
}
blueprint.path.FlushEvents();
return blueprint;
}
}
}
|
|
|
Updating softbody vertex color at runtime |
Posted by: Aroosh - 03-04-2025, 07:32 AM - Forum: Obi Softbody
- Replies (2)
|
 |
Hello
I am using a vertex color shader with softbody and want to update the vertex colors for the mesh. The issue is when I try to get the mesh from Skinner it does not give me the mesh that's currently being used but instead gives the shared mesh.
Thank
Aroosh
|
|
|
How can I detect my second actor in a solver? |
Posted by: anthony_dev - 27-03-2025, 04:05 PM - Forum: Obi Rope
- Replies (9)
|
 |
Hi, I am working on a project where I need to check if a rope is colliding with another rope, if not I will then destroy that rope after enough frames without collision passes.
It is very similar to how `TangledRopes.unity` sample works. I access the solver and on `Solver.OnParticleCollision()`event I call my collision checker function, here's a snippet of the code and my issue:
Code: private void Solver_OnParticleCollision(ObiSolver solver, ObiNativeContactList contacts)
{
for (int i = 0; i < contacts.count; ++i)
{
var ropeA = solver.particleToActor[solver.simplices[contacts[i].bodyA]].actor;
var ropeB = solver.particleToActor[solver.simplices[contacts[i].bodyB]].actor;
if (ropeA == ropeB) //Always true for some reason
{
//Breakpoint
continue;
}
//Do Something
}
}
I never can access to the "Do Something" part of the code. In my debugging I found that EVERY contact is from `Rope_0` and none is from `Rope_1`. The ropes are on top of eachother, even twisted together. They are under the same solver. They are both in group 0 in particles and points in blueprint.
Why may this be?
|
|
|
Obi 7 disable simulation |
Posted by: natko1412 - 27-03-2025, 11:34 AM - Forum: Obi Rope
- Replies (6)
|
 |
Hi, in Obi6 I could disable simulation, but still have rendering done by not running code in custom Updater. How would I do this in new version?
This was my updater before:
Code: using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using Obi;
/// <summary>
/// Updater class that will perform simulation during FixedUpdate(). This is the most physically correct updater,
/// and the one to be used in most cases. Also allows to perform substepping, greatly improving convergence.
//[AddComponentMenu("Physics/Obi/Obi Fixed Updater", 801)]
[ExecuteInEditMode]
public class CustomUpdater : ObiUpdater
{
/// <summary>
/// Each FixedUpdate() call will be divided into several substeps. Performing more substeps will greatly improve the accuracy/convergence speed of the simulation.
/// Increasing the amount of substeps is more effective than increasing the amount of constraint iterations.
/// </summary>
[Tooltip("Amount of substeps performed per FixedUpdate. Increasing the amount of substeps greatly improves accuracy and convergence speed.")]
public int substeps = 4;
public bool solve = false;
private float accumulatedTime;
private void OnValidate()
{
substeps = Mathf.Max(1, substeps);
}
private void Awake()
{
accumulatedTime = 0;
}
private void OnDisable()
{
//Physics.autoSimulation = true;
}
private void FixedUpdate()
{
if (solve)
{
ObiProfiler.EnableProfiler();
BeginStep(Time.fixedDeltaTime);
float substepDelta = Time.fixedDeltaTime / (float)substeps;
// Divide the step into multiple smaller substeps:
for (int i = 0; i < substeps; ++i)
Substep(Time.fixedDeltaTime, substepDelta, substeps - i);
EndStep(substepDelta);
ObiProfiler.DisableProfiler();
accumulatedTime -= Time.fixedDeltaTime;
}
}
private void Update()
{
ObiProfiler.EnableProfiler();
Interpolate(Time.fixedDeltaTime, accumulatedTime);
ObiProfiler.DisableProfiler();
if (solve)
accumulatedTime += Time.deltaTime;
}
}
|
|
|
Reduce particles after blueprint created |
Posted by: webmagic - 25-03-2025, 07:25 AM - Forum: Obi Softbody
- Replies (1)
|
 |
Hi Obi,
we have an rabbit using obi softbody, but we want more efficiency, so we want to reduce particles in specified part, for a rabbit we just want it's ears more soft, but want to reduce other body part's particles.
we successfully deleted the particles (keep the bones particles) and updated the blueprint, but so sad when we start to run , error occured and even ai dont know why:
IndexOutOfRangeException: Reading from index 7926 is out of range of '7920' Capacity.
Obi.ObiNativeList1[T].get_Item (System.Int32 index) (at Assets/Obi/Scripts/Common/DataStructures/NativeList/ObiNativeList.cs:86)
Obi.ObiShapeMatchingConstraintsBatch.Merge (Obi.ObiActor actor, Obi.IObiConstraintsBatch other) (at Assets/Obi/Scripts/Common/Blueprints/Constraints/Batches/ObiShapeMatchingConstraintsBatch.cs:179)
Obi.ObiConstraints1[T].Merge (Obi.ObiActor actor, Obi.IObiConstraints other) (at Assets/Obi/Scripts/Common/Blueprints/Constraints/ObiConstraints.cs:58)
Obi.ObiSolver.PushConstraints () (at Assets/Obi/Scripts/Common/Solver/ObiSolver.cs:2230)
Obi.ObiSolver.StartSimulation (System.Single stepDelta, System.Int32 simulationSteps) (at Assets/Obi/Scripts/Common/Solver/ObiSolver.cs:1647)
Obi.ObiSolver.LateUpdate () (at Assets/Obi/Scripts/Common/Solver/ObiSolver.cs:1169)
the main problem is that looks like when we recreated(updated) the blueprint, something wrong in formart, or the blueprint modified after bind ??
so is it possible to make this happen, or any tips for us, especially which part of obi codes need to read ??
|
|
|
unity6 errors |
Posted by: lacasrac - 23-03-2025, 07:02 PM - Forum: Obi Rope
- Replies (1)
|
 |
System::InvalidOperationException: The UNKNOWN_OBJECT_TYPE has been declared as [ReadOnly] in the job, but you are writing to it.
This Exception was thrown from a job compiled with Burst, which has limited exception support.
0x00007ff81bba26ee (Unity) burst_abort
0x00007ff81bf91b13 (Unity) scripting_raise_exception
0x00007ff81b171a20 (Unity) AtomicSafetyHandle_CUSTOM_CheckWriteAndThrowNoEarlyOut
0x00007ff84667b46e (b17746e930b15012bc57d9fa4529f1d) Unity.Jobs.IJobParallelForExtensions.ParallelForJobStruct`1<Obi.InterpolationJob>.Execute(ref Obi.InterpolationJob jobData, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_1a17c9416545ae7079718413b8a5101d from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null (at E:/UnityProjects/Heimdall/Library/PackageCache/com.unity.burst@7a907cf5a459/.Runtime/unknown/unknown:0)
0x00007ff84667aebd (b17746e930b15012bc57d9fa4529f1d) a4a634249c44e2582a125e65e3f3bb03
Unity 6.0.42f1
Hello,
Can yomebody help me in this? unity 6 hdrp latest, obi7 not working, and pink materials
All the samples are not working 
Thanks, Leslie
|
|
|
|