There are two parts to this question. 

 1. Determine if an object can be placed in a given position.
 2. Find the nearest valid location for an object to be placed.

## 1. Validating Location ##

This one is fairly simple and ultimitely I feel it's the best. 

When the user wants to place an object spawn it in their hands. So they can move it around to determine a position to place it.

In a script on the object respond to the OnCollisionEnter and OnCollisionExit calls. In these methods keep a list of what the object is colliding with. When OnCollisionEnter is hit, store the colliding object in a list and remove it from the list when you see it in the OnCollisionExit call.

Note: while the object is being placed you probably don't want a solid collider for it. So set it's collider to trigger. If you do this then you need to use the OnTriggerEnter and OnTriggerExit methods instead.

While there is an item in the list then the object is colliding with something and can't be placed. Consider swapping the objects material in this state to indicate it.

Then you can simple let the user move it around to a valid location. Letting a user place the object anywhere then "correcting" it for them could cause a disconnect between what the user is trying to do and what the game is doing. 

    using System.Collections.Generic;
    using UnityEngine;
    
    [RequireComponent(typeof(Renderer))]
    public class ObjectPlacer : MonoBehaviour
    {
        private List<GameObject> _collidingObjects = new List<GameObject>();
        private Material _material = null;
        private Color _startingColor = Color.black;
    
        public Color invalidPlacementColor = Color.red;
    
        void Start()
        {
            _material = GetComponent<Renderer>().material;
            _startingColor = _material.color;
        }
    
        void Update()
        {
            if (IsPositionValid())
                _material.color = _startingColor;
            else
                _material.color = invalidPlacementColor;
        }
    
        void OnTriggerEnter(Collider other)
        {
            if (!_collidingObjects.Contains(other.gameObject))
            {
                _collidingObjects.Add(other.gameObject);
                print("Colliding");
            }
        }
    
        void OnTriggerExit(Collider other)
        {
            if (_collidingObjects.Contains(other.gameObject))
            {
                _collidingObjects.Remove(other.gameObject);
            }
        }
    
        bool IsPositionValid()
        {
            return _collidingObjects.Count == 0;
        }
    }

Please note that for this sample code to work I made the colliding object a kinematic rigid body with a trigger collider. The OnTriggerEnter is only triggered if one of the two objects touching is a rigid body and the object the behaviour is on has a collider with "isTrigger" set to true.

## 2. Finding the best location

This part of the problem is fairly hard. The simplest method I can suggest is to use the method in part 1 to determine if you need to do anything. Then iteratively call a method that moves the object away from the collision and check that position.

To check if the object is in a good position you can use a call to [physics.spherecast][1]/[physics.boxcast][2]/[physics.capsulecase][3] and provide parameters that encompass the object being placed. This will give you a [RaycastHit][4] if there is a collision. Move the object along the normal and repeat.

Here's some pseudo code

    
            RaycastHit hit;
            // while the object is colliding move the object by x distance along the normal of collision.
            while (Physics.CapsuleCast(sphereTopPosition, sphereBottomPosition, radius, transform.up, out hit))
            {
                rigidBody.MovePosition(rigidBody.position + hit.normal * someDistance);
            }

The problem with this solution is that you can definitely end up in a situation where the object is just caught in the loop bouncing back and forth between two objects crashing the game. 

  [1]: https://docs.unity3d.com/ScriptReference/Physics.SphereCast.html
  [2]: https://docs.unity3d.com/ScriptReference/Physics.BoxCast.html
  [3]: https://docs.unity3d.com/ScriptReference/Physics.CapsuleCast.html
  [4]: https://docs.unity3d.com/ScriptReference/RaycastHit.html