(09-09-2025, 09:56 AM)Qriva0 Wrote: To be more precise, it's not like it does not work at all, but result seems to be not stable and "physical" in some way?I'm not sure why you have to add force on one particle. Here is what I did:
For example collision is kind of "forced" against various surfaces, especially if it's soft body or cloth, forcing to break constraints and in result less stable.
When it comes to adding force, yes I can add force, but it's not enough to keep rod in place where it supposed to be, so position must be corrected, but it also does not seem fully right, because when movement is a bit faster it kind of breaks (when particle delta is close or larger than distance between particles), I just pull/pull single particle, there is too much violence I guess![]()
I also tried propagate forces in selected part of cable - this helps, but in general I am not satisfied and I want to know how to move it properly or what could be good trick to make it work better.
1. Have an object that is a dynamically attachment of a Obi Rod.
2. Use Unity's AddForceAtPosition to add force at any position to this object
3. Make sure World linear inertia scale/angular inertia scale is set collectly in the Obi solver
If you're not using Unity's AddForceAtPosition you probably need to do something like this. It's copied from AI consult, which I have not tried myself so just FYI:
using Obi;
using UnityEngine;
public class ObiForceAtPosition : MonoBehaviour
{
public ObiActor obiActor; // 你的ObiRope/ObiRod等
public float forceRadius = 1.0f; // 力的作用半径
// 在指定位置施加力
public void AddForceAtPosition(Vector3 force, Vector3 position, ForceMode mode)
{
if (obiActor == null || obiActor.solver == null)
return;
ObiSolver solver = obiActor.solver;
// 遍历所有粒子
foreach (int particleIndex in obiActor.particleIndices)
{
// 获取粒子在世界空间的位置
Vector3 particlePos = solver.transform.TransformPoint(solver.positions[particleIndex]);
float distance = Vector3.Distance(position, particlePos);
// 如果粒子在作用范围内
if (distance <= forceRadius)
{
// 线性衰减权重 (1 -> 0)
float weight = 1 - (distance / forceRadius);
Vector3 particleForce = force * weight;
// 施加力到粒子
solver.ApplyImpulse(particleIndex, particleForce, Vector3.zero);
}
}
}
// 示例:在鼠标点击位置施加力
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
AddForceAtPosition(Vector3.up * 10, hit.point, ForceMode.Impulse);
}
}
}
}